diff --git a/docs/website/src/python-sdk/migration-guide.rst b/docs/website/src/python-sdk/migration-guide.rst index c423520d..3e8b5c57 100644 --- a/docs/website/src/python-sdk/migration-guide.rst +++ b/docs/website/src/python-sdk/migration-guide.rst @@ -16,6 +16,50 @@ Within v0.3: Release-Candidate Changes .. warning:: v0.3 is not released yet, and these changes are breaking *within* v0.3: a contract that ran on an earlier release candidate needs them. They are also folded into the v0.2 sections below +Message Funding +~~~~~~~~~~~~~~~ + +``emit``, ``emit_transfer`` and ``deploy`` accept an optional ``UseBalanceParams`` +as a positional or keyword ``use_balance`` argument. Omission or ``None`` uses +sender funding. Replace ``use_balance=True, fee_params=fees`` with +``use_balance=gl.contract.UseBalanceParams(fee_params=fees)`` + +.. code-block:: python + + target.emit().run() # Sender-funded + target.emit(gl.contract.UseBalanceParams(fees)).run() # Closed + target.emit(use_balance=gl.contract.UseBalanceParams(fees, descendants=100)).run() # Open + target.emit(gl.contract.UseBalanceParams(fees, descendants=[ + gl.message_allocation.InternalAllocation( + recipient=child, call_key="run", fee_params=child_fees, budget=100, + children=[ + gl.message_allocation.InternalAllocation( + recipient=grandchild, call_key="run", fee_params=grandchild_fees, budget=40, + ), + ], + ), + ])).run() # Pinned + target.emit_transfer(1, gl.contract.UseBalanceParams(fees)) + gl.contract.deploy(gl.contract.UseBalanceParams(fees), code=source) + +``descendants=None``, ``0`` and ``[]`` select Closed; a positive integer selects +Open, and a nonempty allocation list selects Pinned. The SDK converts the tree +to a flat list of parent indices; contracts do not need to calculate indices + +For either allocation type, ``call_key=None`` now means any method, equivalent +to ``gl.message_allocation.ANY_METHOD``. Use ``bytes(32)`` for the exact zero +key previously selected by ``None``: internal deploys/transfers and external +calldata shorter than 4 bytes + +Internal allocations accept method names or raw 32-byte keys. External allocations +accept 4-byte EVM selectors, padded on the right to 32 bytes, or raw 32-byte keys +unchanged; strings are rejected. For example, ``call_key=bytes.fromhex("a9059cbb")`` +selects the EVM ``transfer(address,uint256)`` method + +The executor validates topology, positive node budgets and funding inequalities +independently. The example budgets above are illustrative; actual budgets must +cover primary fees and descendants, including the applicable appeal multiplier + Pre-finalization State Is ``decided`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/executor/codegen/data/public-abi.json b/executor/codegen/data/public-abi.json index 60e8d241..7e7218f9 100644 --- a/executor/codegen/data/public-abi.json +++ b/executor/codegen/data/public-abi.json @@ -175,7 +175,11 @@ ] }, "below_minimum", - "too_many_rounds" + "too_many_rounds", + { + "head": "descendant_grant", + "tail": ["budget", "tree", "external"] + } ] }, "forbidden", diff --git a/executor/crates/calldata/src/codec/de/builtin.rs b/executor/crates/calldata/src/codec/de/builtin.rs index d06620a4..6f201f65 100644 --- a/executor/crates/calldata/src/codec/de/builtin.rs +++ b/executor/crates/calldata/src/codec/de/builtin.rs @@ -314,8 +314,8 @@ impl Decode for Vec { struct V(std::marker::PhantomData); impl Visitor for V { type Value = Vec; - fn visit_seq(self, len: u64, mut seq: A) -> Result, DecodeError> { - let mut result = Vec::with_capacity(len as usize); + fn visit_seq(self, _len: u64, mut seq: A) -> Result, DecodeError> { + let mut result = Vec::new(); while let Some(elem) = seq.next_element::()? { result.push(elem); } @@ -452,3 +452,45 @@ impl Decode for std::rc::Rc { T::validate(deserializer) } } + +#[cfg(test)] +mod tests { + use crate::Value; + + use super::super::{Decode, DecodeError, Deserializer, SeqAccess, ValueDeserializer, Visitor}; + + struct InflatedLen; + + impl Deserializer for InflatedLen { + fn deserialize(self, visitor: V) -> Result { + visitor.visit_seq(1_000_000, OneBool(true)) + } + } + + struct OneBool(bool); + + impl SeqAccess for OneBool { + fn next_element(&mut self) -> Result, DecodeError> { + if std::mem::take(&mut self.0) { + T::decode(ValueDeserializer(Value::Bool(true))).map(Some) + } else { + Ok(None) + } + } + + fn next_element_validate(&mut self) -> Result, DecodeError> { + self.next_element::().map(|value| value.map(drop)) + } + } + + #[test] + fn sequence_decoders_do_not_trust_declared_capacity() { + let decoded = Vec::::decode(InflatedLen).unwrap(); + assert!(decoded.capacity() < 1_000_000); + + let Value::Array(decoded) = Value::decode(InflatedLen).unwrap() else { + panic!("expected array"); + }; + assert!(decoded.capacity() < 1_000_000); + } +} diff --git a/executor/crates/calldata/src/codec/de/value.rs b/executor/crates/calldata/src/codec/de/value.rs index a4fd057c..161e0d4c 100644 --- a/executor/crates/calldata/src/codec/de/value.rs +++ b/executor/crates/calldata/src/codec/de/value.rs @@ -94,8 +94,8 @@ impl Decode for Value { Ok(Value::Bytes(value.to_vec())) } - fn visit_seq(self, len: u64, mut seq: A) -> Result { - let mut result = Vec::with_capacity(len as usize); + fn visit_seq(self, _len: u64, mut seq: A) -> Result { + let mut result = Vec::new(); while let Some(elem) = seq.next_element::()? { result.push(elem); } diff --git a/executor/crates/sdk-rs/src/abi/consts.rs b/executor/crates/sdk-rs/src/abi/consts.rs index 914ee6ee..31f8d001 100644 --- a/executor/crates/sdk-rs/src/abi/consts.rs +++ b/executor/crates/sdk-rs/src/abi/consts.rs @@ -397,6 +397,17 @@ pub mod __VmError { } } + pub struct FeeDescendantGrant; + + impl FeeDescendantGrant { + pub const fn prefix_(&self) -> &'static str { + "fee descendant_grant" + } + pub const fn budget(&self) -> VmError { VmError(Cow::Borrowed("fee descendant_grant budget")) } + pub const fn tree(&self) -> VmError { VmError(Cow::Borrowed("fee descendant_grant tree")) } + pub const fn external(&self) -> VmError { VmError(Cow::Borrowed("fee descendant_grant external")) } + } + pub struct Fee; impl Fee { @@ -406,6 +417,7 @@ pub mod __VmError { pub const fn below_minimum(&self) -> VmError { VmError(Cow::Borrowed("fee below_minimum")) } pub const fn too_many_rounds(&self) -> VmError { VmError(Cow::Borrowed("fee too_many_rounds")) } pub const fn no_matching_allocation(&self) -> FeeNoMatchingAllocation { FeeNoMatchingAllocation } + pub const fn descendant_grant(&self) -> FeeDescendantGrant { FeeDescendantGrant } } pub struct Evm; @@ -525,6 +537,9 @@ impl VmError { "fee no_matching_allocation" | "fee below_minimum" | "fee too_many_rounds" | + "fee descendant_grant budget" | + "fee descendant_grant tree" | + "fee descendant_grant external" | "forbidden" | "evm reverted" | "invalid_contract" | diff --git a/executor/crates/sdk-rs/src/abi/fees.rs b/executor/crates/sdk-rs/src/abi/fees.rs index ba3679e7..e6eddbca 100644 --- a/executor/crates/sdk-rs/src/abi/fees.rs +++ b/executor/crates/sdk-rs/src/abi/fees.rs @@ -18,8 +18,11 @@ use primitive_types::U256; genlayer_calldata::Encode, genlayer_calldata::Decode, )] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct ExternalMessageParams { + #[cfg_attr(feature = "fuzzing", arbitrary(with = crate::abi::arb::arb_u256))] pub gas_limit: U256, + #[cfg_attr(feature = "fuzzing", arbitrary(with = crate::abi::arb::arb_u256))] pub max_gas_price: U256, } diff --git a/executor/crates/sdk-rs/src/abi/gl_call.rs b/executor/crates/sdk-rs/src/abi/gl_call.rs index 87aec1dd..3a64f73a 100644 --- a/executor/crates/sdk-rs/src/abi/gl_call.rs +++ b/executor/crates/sdk-rs/src/abi/gl_call.rs @@ -486,6 +486,84 @@ pub enum On { Decided, } +#[derive(Clone, PartialEq, Eq, Debug, Encode)] +#[calldata(untagged)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +pub enum Descendants { + Open( + #[cfg_attr(feature = "fuzzing", arbitrary(with = crate::abi::arb::arb_u256))] + primitive_types::U256, + ), + Pinned(Vec), +} + +impl calldata::codec::Decode for Descendants { + fn decode( + deserializer: D, + ) -> Result { + use calldata::codec::{ + Decode, DecodeError, Deserializer, SeqAccess, ValueDeserializer, Visitor, + }; + + struct V; + impl Visitor for V { + type Value = Descendants; + + fn visit_bigint(self, value: &num_bigint::BigInt) -> Result { + primitive_types::U256::decode(ValueDeserializer(calldata::Value::Number( + value.clone(), + ))) + .map(Descendants::Open) + } + + fn visit_seq(self, len: u64, seq: A) -> Result { + struct Sequence(u64, A); + impl Deserializer for Sequence { + fn deserialize(self, visitor: V) -> Result { + visitor.visit_seq(self.0, self.1) + } + } + calldata::LenLimitedVec::<1024, AllocationNode>::decode(Sequence(len, seq)) + .map(|nodes| Descendants::Pinned(nodes.into_inner())) + } + } + deserializer.deserialize(V) + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] +#[calldata(untagged)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +pub enum AllocationNode { + Internal(InternalAllocation), + External(ExternalAllocation), +} + +#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +pub struct InternalAllocation { + #[cfg_attr(feature = "fuzzing", arbitrary(with = crate::abi::arb::arb_u256))] + pub parent_index: primitive_types::U256, + pub recipient: calldata::Address, + pub call_key: abi::CallKey, + #[cfg_attr(feature = "fuzzing", arbitrary(with = crate::abi::arb::arb_u256))] + pub budget: primitive_types::U256, + pub fee_params: fees::InternalMessageParams, + pub on: On, +} + +#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] +pub struct ExternalAllocation { + #[cfg_attr(feature = "fuzzing", arbitrary(with = crate::abi::arb::arb_u256))] + pub parent_index: primitive_types::U256, + pub recipient: calldata::Address, + pub call_key: abi::CallKey, + #[cfg_attr(feature = "fuzzing", arbitrary(with = crate::abi::arb::arb_u256))] + pub budget: primitive_types::U256, + pub fee_params: fees::ExternalMessageParams, +} + fn encode_storage_view( view: &public_abi::StorageView, enc: &mut calldata::Encoder, @@ -581,6 +659,9 @@ pub enum Message { /// only honored when `use_balance` is set. #[calldata(default = default_none)] fee_params: Option, + /// Descendant funding policy for the emitted child + #[calldata(default = default_none)] + descendants: Option, }, EmitInternalDeployMessage { calldata: abi::entry::MainDeployData, @@ -597,6 +678,9 @@ pub enum Message { /// Guest fee params for the balance-funded deploy; see `EmitInternalMessage::fee_params`. #[calldata(default = default_none)] fee_params: Option, + /// Descendant funding policy for the emitted child + #[calldata(default = default_none)] + descendants: Option, }, EmitEvent { #[cfg_attr(feature = "fuzzing", arbitrary(with = crate::abi::arb::arb_limited_vec_bytes))] diff --git a/executor/crates/sdk-rs/src/abi/mod.rs b/executor/crates/sdk-rs/src/abi/mod.rs index 7935f0b3..870bcfdb 100644 --- a/executor/crates/sdk-rs/src/abi/mod.rs +++ b/executor/crates/sdk-rs/src/abi/mod.rs @@ -32,6 +32,7 @@ pub mod wasi; serde::Serialize, serde::Deserialize, )] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct CallKey( #[calldata( serialize_with = ::genlayer_calldata::codec::as_bytes::serialize, diff --git a/executor/crates/sdk-rs/tests/gl_call_balance_fees.rs b/executor/crates/sdk-rs/tests/gl_call_balance_fees.rs index b8347eba..75a99c69 100644 --- a/executor/crates/sdk-rs/tests/gl_call_balance_fees.rs +++ b/executor/crates/sdk-rs/tests/gl_call_balance_fees.rs @@ -1,10 +1,13 @@ -//! Backward-compat / round-trip coverage for the balance-funded fee fields -//! (`use_balance`, `fee_params`) added to `EmitInternalMessage` / -//! `EmitInternalDeployMessage`. +//! Backward-compat / round-trip coverage for balance-funded message fields. -use genlayer_sdk::abi::fees::InternalMessageParams; -use genlayer_sdk::abi::gl_call::{Message, On}; -use genlayer_sdk::calldata::codec::{BinaryDeserializer, Decode}; +use std::collections::BTreeMap; + +use genlayer_sdk::abi::CallKey; +use genlayer_sdk::abi::fees::{ExternalMessageParams, InternalMessageParams}; +use genlayer_sdk::abi::gl_call::{ + AllocationNode, Descendants, ExternalAllocation, InternalAllocation, Message, On, +}; +use genlayer_sdk::calldata::codec::{BinaryDeserializer, Decode, ValueDeserializer}; use genlayer_sdk::calldata::unparsed::Maybe; use genlayer_sdk::calldata::{self, Encoder, Value}; use primitive_types::U256; @@ -30,6 +33,12 @@ fn sample_params() -> InternalMessageParams { } } +fn address(last: u8) -> calldata::Address { + let mut raw = [0; 20]; + raw[19] = last; + calldata::Address::from(raw) +} + /// A message carrying the two new fields round-trips through the calldata codec. #[test] fn emit_internal_message_balance_fields_round_trip() { @@ -45,6 +54,7 @@ fn emit_internal_message_balance_fields_round_trip() { on: On::Finalized, use_balance: true, fee_params: Some(params.clone()), + descendants: Some(Descendants::Open(U256::from(11u64))), }; let decoded: Message = Decode::decode(BinaryDeserializer::new(&encode!(msg))).unwrap(); @@ -53,17 +63,67 @@ fn emit_internal_message_balance_fields_round_trip() { Message::EmitInternalMessage { use_balance, fee_params, + descendants, value, .. } => { assert!(use_balance); assert_eq!(fee_params, Some(params)); + assert_eq!(descendants, Some(Descendants::Open(U256::from(11u64)))); assert_eq!(value, U256::from(42u64)); } other => panic!("expected EmitInternalMessage, got {other:?}"), } } +#[test] +fn emit_internal_deploy_message_balance_fields_round_trip() { + let params = sample_params(); + let descendants = Descendants::Pinned(vec![AllocationNode::External(ExternalAllocation { + parent_index: U256::MAX, + recipient: address(0x33), + call_key: CallKey([7; 32]), + budget: U256::from(200u64), + fee_params: ExternalMessageParams { + gas_limit: U256::from(20u64), + max_gas_price: U256::from(10u64), + }, + })]); + let msg = Message::EmitInternalDeployMessage { + calldata: genlayer_sdk::abi::entry::MainDeployData { + args: None, + kwargs: None, + }, + code: bytes::Bytes::from_static(b"code"), + value: U256::from(42u64), + on: On::Decided, + salt_nonce: U256::from(3u64), + use_balance: true, + fee_params: Some(params.clone()), + descendants: Some(descendants.clone()), + }; + + let decoded: Message = Decode::decode(BinaryDeserializer::new(&encode!(msg))).unwrap(); + + match decoded { + Message::EmitInternalDeployMessage { + use_balance, + fee_params, + descendants: decoded_descendants, + value, + on, + .. + } => { + assert!(use_balance); + assert_eq!(fee_params, Some(params)); + assert_eq!(decoded_descendants, Some(descendants)); + assert_eq!(value, U256::from(42u64)); + assert_eq!(on, On::Decided); + } + other => panic!("expected EmitInternalDeployMessage, got {other:?}"), + } +} + /// An `EmitInternalMessage` map produced before the fields existed (no `use_balance` / /// `fee_params` keys) decodes with the defaults. #[test] @@ -94,10 +154,12 @@ fn emit_internal_message_old_encoding_defaults() { Message::EmitInternalMessage { use_balance, fee_params, + descendants, .. } => { assert!(!use_balance); assert!(fee_params.is_none()); + assert!(descendants.is_none()); } other => panic!("expected EmitInternalMessage, got {other:?}"), } @@ -132,11 +194,197 @@ fn emit_internal_deploy_message_old_encoding_defaults() { Message::EmitInternalDeployMessage { use_balance, fee_params, + descendants, .. } => { assert!(!use_balance); assert!(fee_params.is_none()); + assert!(descendants.is_none()); } other => panic!("expected EmitInternalDeployMessage, got {other:?}"), } } + +#[test] +fn emit_internal_message_explicit_null_descendants_decode_as_absent() { + #[derive(calldata::Encode)] + enum RawMessage { + #[allow(dead_code)] + EmitInternalMessage { + address: calldata::Address, + calldata: Maybe, + value: U256, + on: On, + use_balance: bool, + fee_params: Option, + descendants: Value, + }, + } + + let raw = RawMessage::EmitInternalMessage { + address: calldata::Address::zero(), + calldata: Maybe::Materialized(Value::Map(Default::default())), + value: U256::zero(), + on: On::Finalized, + use_balance: false, + fee_params: None, + descendants: Value::Null, + }; + + let decoded: Message = Decode::decode(BinaryDeserializer::new(&encode!(raw))).unwrap(); + match decoded { + Message::EmitInternalMessage { + use_balance, + descendants, + .. + } => { + assert!(!use_balance); + assert!(descendants.is_none()); + } + other => panic!("expected EmitInternalMessage, got {other:?}"), + } +} + +#[test] +fn pinned_descendants_round_trip_flat_mixed_nodes() { + let child = AllocationNode::Internal(InternalAllocation { + recipient: address(0x22), + call_key: CallKey::DEPLOY, + budget: U256::from(20u64), + fee_params: sample_params(), + on: On::Decided, + parent_index: U256::zero(), + }); + let descendants = Descendants::Pinned(vec![ + AllocationNode::Internal(InternalAllocation { + recipient: address(0x11), + call_key: CallKey::for_method("run"), + budget: U256::from(60u64), + fee_params: sample_params(), + on: On::Finalized, + parent_index: U256::MAX, + }), + child, + AllocationNode::External(ExternalAllocation { + parent_index: U256::MAX, + recipient: address(0x33), + call_key: CallKey([7; 32]), + budget: U256::from(200u64), + fee_params: ExternalMessageParams { + gas_limit: U256::from(20u64), + max_gas_price: U256::from(10u64), + }, + }), + ]); + + let decoded: Descendants = + Decode::decode(BinaryDeserializer::new(&encode!(descendants.clone()))).unwrap(); + assert_eq!(decoded, descendants); +} + +fn external_allocation_value() -> BTreeMap { + BTreeMap::from([ + ("parent_index".into(), Value::from(U256::MAX)), + ("recipient".into(), Value::from(address(0x33))), + ("call_key".into(), Value::Bytes(vec![0; 32])), + ("budget".into(), Value::from(200u64)), + ( + "fee_params".into(), + Value::Map(BTreeMap::from([ + ("gas_limit".into(), Value::from(20u64)), + ("max_gas_price".into(), Value::from(10u64)), + ])), + ), + ]) +} + +fn internal_allocation_value() -> BTreeMap { + BTreeMap::from([ + ("parent_index".into(), Value::from(U256::MAX)), + ("recipient".into(), Value::from(address(0x11))), + ("call_key".into(), Value::Bytes(vec![0; 32])), + ("budget".into(), Value::from(300u64)), + ( + "fee_params".into(), + Value::Map(BTreeMap::from([ + ("leader_time_units_allocation".into(), Value::from(5u64)), + ("validator_time_units_allocation".into(), Value::from(7u64)), + ("execution_budget_per_round".into(), Value::from(1024u64)), + ("rotations".into(), Value::Array(vec![Value::from(4u64)])), + ("max_price_gen_per_time_unit".into(), Value::from(9u64)), + ("storage_fee_max_gas_price".into(), Value::from(20u64)), + ("receipt_fee_max_gas_price".into(), Value::from(20u64)), + ])), + ), + ]) +} + +#[test] +fn descendants_reject_bool_instead_of_open_budget() { + let err = Descendants::decode(ValueDeserializer(Value::Bool(true))).unwrap_err(); + assert!( + err.to_string().contains("unexpected"), + "unexpected error: {err}" + ); +} + +#[test] +fn external_allocation_rejects_children_key() { + let mut fields = external_allocation_value(); + fields.insert("children".into(), Value::Array(vec![])); + let err = ExternalAllocation::decode(ValueDeserializer(Value::Map(fields))).unwrap_err(); + assert!( + err.to_string().contains("unknown field"), + "unexpected error: {err}" + ); +} + +#[test] +fn external_allocation_rejects_missing_fee_params() { + let mut fields = external_allocation_value(); + fields.remove("fee_params"); + let err = ExternalAllocation::decode(ValueDeserializer(Value::Map(fields))).unwrap_err(); + assert!( + err.to_string().contains("field missing"), + "unexpected error: {err}" + ); +} + +#[test] +fn allocation_node_rejects_internal_shape_missing_on() { + let result = AllocationNode::decode(ValueDeserializer(Value::Map(internal_allocation_value()))); + assert!(result.is_err()); +} + +#[test] +fn descendants_decode_limit_precedes_node_decoding() { + let oversized = Value::Array(vec![Value::Null; 1025]); + let error = + Descendants::decode(BinaryDeserializer::new(&calldata::encode(&oversized))).unwrap_err(); + assert!( + error.to_string().contains("expected 1024 elements"), + "unexpected error: {error}" + ); +} + +#[test] +fn descendants_decode_accepts_limit_and_rejects_recursive_shapes() { + let nodes = Value::Array(vec![Value::Map(external_allocation_value()); 1024]); + let decoded = Descendants::decode(BinaryDeserializer::new(&calldata::encode(&nodes))).unwrap(); + let Descendants::Pinned(nodes) = decoded else { + panic!("expected pinned descendants") + }; + assert_eq!(nodes.len(), 1024); + + let mut node = internal_allocation_value(); + node.insert("on".into(), Value::Str("finalized".into())); + node.insert("children".into(), Value::Array(vec![])); + let error = InternalAllocation::decode(BinaryDeserializer::new(&calldata::encode( + &Value::Map(node), + ))) + .unwrap_err(); + assert!( + error.to_string().contains("unknown field"), + "unexpected error: {error}" + ); +} diff --git a/executor/install/config/genvm.yaml b/executor/install/config/genvm.yaml index 739db8b4..2d4c3427 100644 --- a/executor/install/config/genvm.yaml +++ b/executor/install/config/genvm.yaml @@ -171,7 +171,7 @@ fees: # Each `bytes` field is length + data, rounded up to 32 bytes. The extra # calldata word conservatively covers the internal RLP wrapper let calldataBytes = 32 + 32 + ceilDiv a.calldataLength 32 * 32 in - # allocationSubtree is empty for external and balance-funded messages + # allocationSubtree is empty for external and Closed balance-funded messages let subtreeBytes = 32 + 32 + ceilDiv a.subtreeLength 32 * 32 in # Internal fee params have an outer offset, 8-word head, and rotations # array; external fee params are a static 2-word tuple @@ -238,7 +238,8 @@ fees: # reject only a non-zero per-round budget below the floor (matches the # chain's `execBudget > 0 && execBudget < floor`) let budgetTooLow = - if a.matchedFeeParams.executionBudgetPerRound > 0 + if a.skipBudgetFloor then false + else if a.matchedFeeParams.executionBudgetPerRound > 0 then a.matchedFeeParams.executionBudgetPerRound < budgetFloor else false in if a.isInternal diff --git a/executor/src/rt/fees.rs b/executor/src/rt/fees.rs index 04ccec64..90cb6a6b 100644 --- a/executor/src/rt/fees.rs +++ b/executor/src/rt/fees.rs @@ -606,11 +606,27 @@ impl DataLimit { pub fn calculate_message_fee_internal( &self, matched_fee_params: &genlayer_sdk::abi::fees::InternalMessageParams, + ) -> rt::errors::Result { + self.calculate_message_fee_internal_impl(matched_fee_params, false) + } + + pub fn calculate_descendant_message_fee_internal( + &self, + matched_fee_params: &genlayer_sdk::abi::fees::InternalMessageParams, + ) -> rt::errors::Result { + self.calculate_message_fee_internal_impl(matched_fee_params, true) + } + + fn calculate_message_fee_internal_impl( + &self, + matched_fee_params: &genlayer_sdk::abi::fees::InternalMessageParams, + skip_budget_floor: bool, ) -> rt::errors::Result { self.calculate_bucket( &self.message_fee, &[ ("isInternal", true.into()), + ("skipBudgetFloor", skip_budget_floor.into()), ( "matchedFeeParams", fee_params_value_internal(matched_fee_params), diff --git a/executor/src/wasi/genlayer_sdk/descendant_grant.rs b/executor/src/wasi/genlayer_sdk/descendant_grant.rs new file mode 100644 index 00000000..85796011 --- /dev/null +++ b/executor/src/wasi/genlayer_sdk/descendant_grant.rs @@ -0,0 +1,332 @@ +use genlayer_sdk::abi; +use primitive_types::U256; +use std::collections::BTreeSet; + +use super::message::internal_params_valid; +use crate::rt; + +const DOMAIN: [u8; 32] = [ + 0x5f, 0x77, 0x18, 0x1a, 0x28, 0xfb, 0x88, 0xdd, 0x05, 0x97, 0x39, 0x0f, 0x85, 0x2a, 0x7f, 0x17, + 0x4b, 0xad, 0x95, 0x30, 0x3d, 0xef, 0xee, 0xfb, 0x5b, 0xa8, 0x06, 0xaa, 0xa3, 0xef, 0x64, 0xfb, +]; + +pub(super) const ROOT_PARENT: U256 = U256::MAX; +const MAX_NODES: usize = 24; +const MAX_FEE_PARAMS_BYTES: usize = 1_024; +const INTERNAL_FEE_PARAMS_BASE_BYTES: usize = 320; +const MAX_INTERNAL_ROTATIONS: usize = (MAX_FEE_PARAMS_BYTES - INTERNAL_FEE_PARAMS_BASE_BYTES) / 32; +const MAX_GRANT_BYTES: usize = 31_712; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub(super) enum GrantPolicy { + #[cfg(test)] + Closed = 0, + Open = 1, + Pinned = 2, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub(super) enum AllocationFeeParams { + External(abi::fees::ExternalMessageParams), + Internal(abi::fees::InternalMessageParams), +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub(super) struct FlatAllocation { + pub on_acceptance: bool, + pub parent_index: U256, + pub recipient: genlayer_calldata::Address, + pub call_key: abi::CallKey, + pub budget: U256, + pub fee_params: AllocationFeeParams, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub(super) struct Grant { + pub policy: GrantPolicy, + pub budget: U256, + pub allocations: Vec, +} + +#[derive(Debug)] +pub(super) enum GrantValidationError { + Inval, + Budget, + Tree, + External, + Internal(rt::errors::Error), +} + +#[derive(Debug, PartialEq, Eq)] +pub(super) struct PreparedGrant { + pub budget: U256, + pub subtree: Vec, +} + +fn push_word(output: &mut Vec, value: U256) { + output.extend_from_slice(&value.to_big_endian()); +} + +fn push_usize(output: &mut Vec, value: usize) { + push_word(output, U256::from(value)); +} + +fn push_address(output: &mut Vec, address: genlayer_calldata::Address) { + output.extend_from_slice(&[0; 12]); + output.extend_from_slice(&address.raw()); +} + +fn encode_bytes(value: &[u8]) -> Vec { + let padded_len = value.len().div_ceil(32) * 32; + let mut output = Vec::with_capacity(32 + padded_len); + push_usize(&mut output, value.len()); + output.extend_from_slice(value); + output.resize(32 + padded_len, 0); + output +} + +fn encode_internal_fee_params(params: &abi::fees::InternalMessageParams) -> Vec { + let mut output = Vec::with_capacity(320 + params.rotations.len() * 32); + push_usize(&mut output, 32); + push_word(&mut output, params.leader_time_units_allocation); + push_word(&mut output, params.validator_time_units_allocation); + push_usize( + &mut output, + params + .rotations + .len() + .checked_sub(1) + .expect("validated rotations must be non-empty"), + ); + push_word(&mut output, params.execution_budget_per_round); + push_usize(&mut output, 8 * 32); + push_word(&mut output, params.max_price_gen_per_time_unit); + push_word(&mut output, params.storage_fee_max_gas_price); + push_word(&mut output, params.receipt_fee_max_gas_price); + push_usize(&mut output, params.rotations.len()); + for rotation in ¶ms.rotations { + push_word(&mut output, *rotation); + } + output +} + +fn encode_external_fee_params(params: &abi::fees::ExternalMessageParams) -> Vec { + let mut output = Vec::with_capacity(64); + push_word(&mut output, params.gas_limit); + push_word(&mut output, params.max_gas_price); + output +} + +fn encode_allocation(node: &FlatAllocation) -> Vec { + let (message_type, fee_params) = match &node.fee_params { + AllocationFeeParams::External(params) => (0, encode_external_fee_params(params)), + AllocationFeeParams::Internal(params) => (1, encode_internal_fee_params(params)), + }; + let mut output = Vec::with_capacity(256 + fee_params.len().next_multiple_of(32)); + push_usize(&mut output, message_type); + push_usize(&mut output, usize::from(node.on_acceptance)); + push_word(&mut output, node.parent_index); + push_address(&mut output, node.recipient); + output.extend_from_slice(&node.call_key.0); + push_word(&mut output, node.budget); + push_usize(&mut output, 7 * 32); + output.extend_from_slice(&encode_bytes(&fee_params)); + output +} + +pub(super) fn encode_grant(grant: &Grant) -> Vec { + let encoded_nodes = grant + .allocations + .iter() + .map(encode_allocation) + .collect::>(); + + let mut allocations = Vec::new(); + push_usize(&mut allocations, encoded_nodes.len()); + let mut offset = encoded_nodes.len() * 32; + for node in &encoded_nodes { + push_usize(&mut allocations, offset); + offset += node.len(); + } + for node in encoded_nodes { + allocations.extend_from_slice(&node); + } + + let mut output = Vec::with_capacity(64 + 128 + allocations.len()); + output.extend_from_slice(&DOMAIN); + push_usize(&mut output, 64); + push_usize(&mut output, 1); + push_usize(&mut output, grant.policy as usize); + push_word(&mut output, grant.budget); + push_usize(&mut output, 4 * 32); + output.extend_from_slice(&allocations); + output +} + +fn sibling_key(node: &abi::gl_call::AllocationNode) -> (u8, [u8; 20], [u8; 32]) { + match node { + abi::gl_call::AllocationNode::Internal(node) => (1, node.recipient.raw(), node.call_key.0), + abi::gl_call::AllocationNode::External(node) => (0, node.recipient.raw(), node.call_key.0), + } +} + +fn validate_nodes( + nodes: &[abi::gl_call::AllocationNode], + enclosing_rotations: usize, + quote: &mut F, +) -> Result +where + F: FnMut(&abi::fees::InternalMessageParams) -> rt::errors::Result, +{ + if nodes.len() > MAX_NODES { + return Err(GrantValidationError::Tree); + } + let mut budget = U256::zero(); + let mut children_budgets = vec![U256::zero(); nodes.len()]; + let mut sibling_keys = BTreeSet::new(); + for (index, node) in nodes.iter().enumerate() { + let (parent_index, node_budget) = match node { + abi::gl_call::AllocationNode::Internal(node) => (node.parent_index, node.budget), + abi::gl_call::AllocationNode::External(node) => (node.parent_index, node.budget), + }; + if node_budget.is_zero() { + return Err(GrantValidationError::Budget); + } + if !sibling_keys.insert((parent_index, sibling_key(node))) { + return Err(GrantValidationError::Tree); + } + let total = if parent_index == ROOT_PARENT { + &mut budget + } else { + if parent_index >= U256::from(index) + || !matches!( + nodes[parent_index.as_usize()], + abi::gl_call::AllocationNode::Internal(_) + ) + || matches!(node, abi::gl_call::AllocationNode::External(_)) + { + return Err(GrantValidationError::Tree); + } + &mut children_budgets[parent_index.as_usize()] + }; + *total = total + .checked_add(node_budget) + .ok_or(GrantValidationError::Budget)?; + } + + let mut allocations = Vec::with_capacity(nodes.len()); + for (index, node) in nodes.iter().enumerate() { + match node { + abi::gl_call::AllocationNode::Internal(node) => { + if !internal_params_valid(&node.fee_params) + || node.fee_params.rotations.len() > MAX_INTERNAL_ROTATIONS + { + return Err(GrantValidationError::Inval); + } + + allocations.push(FlatAllocation { + on_acceptance: matches!(node.on, abi::gl_call::On::Decided), + parent_index: node.parent_index, + recipient: node.recipient, + call_key: node.call_key, + budget: node.budget, + fee_params: AllocationFeeParams::Internal(node.fee_params.clone()), + }); + let parent_rotations = if node.parent_index == ROOT_PARENT { + enclosing_rotations + } else { + let abi::gl_call::AllocationNode::Internal(parent) = + &nodes[node.parent_index.as_usize()] + else { + unreachable!("parent type validated above") + }; + parent.fee_params.rotations.len() + }; + let primary = quote(&node.fee_params).map_err(GrantValidationError::Internal)?; + let required = primary + .checked_add(children_budgets[index]) + .and_then(|amount| { + if matches!(node.on, abi::gl_call::On::Decided) { + amount.checked_mul(U256::from(parent_rotations)) + } else { + Some(amount) + } + }) + .ok_or(GrantValidationError::Budget)?; + if node.budget < required { + return Err(GrantValidationError::Budget); + } + } + abi::gl_call::AllocationNode::External(node) => { + // The transaction-pinned minimum external gas limit is not available in host input yet. + let unit = node + .fee_params + .gas_limit + .checked_mul(node.fee_params.max_gas_price) + .filter(|unit| !unit.is_zero()) + .ok_or(GrantValidationError::External)?; + if node.budget < unit || node.budget % unit != U256::zero() { + return Err(GrantValidationError::External); + } + allocations.push(FlatAllocation { + on_acceptance: false, + parent_index: node.parent_index, + recipient: node.recipient, + call_key: node.call_key, + budget: node.budget, + fee_params: AllocationFeeParams::External(node.fee_params), + }); + } + } + } + Ok(Grant { + policy: GrantPolicy::Pinned, + budget, + allocations, + }) +} + +pub(super) fn prepare_descendants( + enclosing_params: &abi::fees::InternalMessageParams, + descendants: Option, + mut quote: F, +) -> Result +where + F: FnMut(&abi::fees::InternalMessageParams) -> rt::errors::Result, +{ + let grant = match descendants { + None => { + return Ok(PreparedGrant { + budget: U256::zero(), + subtree: vec![], + }); + } + Some(abi::gl_call::Descendants::Open(budget)) if budget.is_zero() => { + return Ok(PreparedGrant { + budget: U256::zero(), + subtree: vec![], + }); + } + Some(abi::gl_call::Descendants::Pinned(ref nodes)) if nodes.is_empty() => { + return Ok(PreparedGrant { + budget: U256::zero(), + subtree: vec![], + }); + } + Some(abi::gl_call::Descendants::Open(budget)) => Grant { + policy: GrantPolicy::Open, + budget, + allocations: vec![], + }, + Some(abi::gl_call::Descendants::Pinned(nodes)) => { + validate_nodes(&nodes, enclosing_params.rotations.len(), &mut quote)? + } + }; + + let subtree = encode_grant(&grant); + debug_assert!(subtree.len() <= MAX_GRANT_BYTES); + Ok(PreparedGrant { + budget: grant.budget, + subtree, + }) +} diff --git a/executor/src/wasi/genlayer_sdk/message.rs b/executor/src/wasi/genlayer_sdk/message.rs index 8b7cd4db..d77234d8 100644 --- a/executor/src/wasi/genlayer_sdk/message.rs +++ b/executor/src/wasi/genlayer_sdk/message.rs @@ -1,3 +1,4 @@ +use super::descendant_grant::{prepare_descendants, GrantValidationError, PreparedGrant}; use super::*; fn allocation_match_priority( @@ -97,18 +98,73 @@ enum FeeFunding<'a> { node: &'a genvm_modules_interfaces::fees::MessageAllocationNode, consumed: &'a mut primitive_types::U256, }, - /// Balance-funded (`useBalance`): the metered fee is the `declaredBudget`, - /// reserved from the contract balance. On-chain such messages are excluded - /// from the sender pool, so the message-fee bucket is skipped and only the - /// receipt is charged. The balance is checked here, before the receipt is - /// consumed, so nothing is charged unless funding is guaranteed. + /// Balance-funded (`useBalance`): the primary fee plus the descendant grant + /// budget is the `declaredBudget`, reserved from the contract balance. Such + /// messages skip the sender pool and message-fee bucket. The balance is + /// checked before receipt consumption, so failed funding charges nothing. Balance { value: primitive_types::U256, messages_value_decremented: primitive_types::U256, my_balance: primitive_types::U256, + fee_cost: rt::fees::CostVec, }, } +fn grant_validation_error(error: GrantValidationError) -> generated::types::Error { + match error { + GrantValidationError::Inval => generated::types::Errno::Inval.into(), + GrantValidationError::Budget => internal_trap(rt::errors::Error::vm( + abi::consts::VmError::fee().descendant_grant().budget(), + )), + GrantValidationError::Tree => internal_trap(rt::errors::Error::vm( + abi::consts::VmError::fee().descendant_grant().tree(), + )), + GrantValidationError::External => internal_trap(rt::errors::Error::vm( + abi::consts::VmError::fee().descendant_grant().external(), + )), + GrantValidationError::Internal(error) => internal_trap(error), + } +} + +fn prepare_grant( + data_fees_limit: &rt::fees::DataLimit, + fee_params: Option<&abi::fees::InternalMessageParams>, + descendants: Option, +) -> Result { + match (fee_params, descendants) { + (None, None) => Ok(PreparedGrant { + budget: primitive_types::U256::zero(), + subtree: vec![], + }), + (None, Some(_)) => Err(generated::types::Errno::Inval.into()), + (Some(params), descendants) => { + // The transaction-pinned primary quote is not in host input; preserve the existing quote. + prepare_descendants(params, descendants, |node_params| { + data_fees_limit + .calculate_descendant_message_fee_internal(node_params) + .map(|cost| cost.reported_fee()) + }) + .map_err(grant_validation_error) + } + } +} + +fn balance_fee_cost( + data_fees_limit: &rt::fees::DataLimit, + fee_params: &abi::fees::InternalMessageParams, + descendant_budget: primitive_types::U256, +) -> Result { + let mut fee_cost = data_fees_limit + .calculate_message_fee_internal(fee_params) + .map_err(internal_trap)?; + fee_cost.0[0] = fee_cost + .reported_fee() + .checked_add(descendant_budget) + .ok_or(GrantValidationError::Budget) + .map_err(grant_validation_error)?; + Ok(fee_cost) +} + fn convert_on_to_modules(on: gl_call::On) -> genvm_modules_interfaces::On { match on { gl_call::On::Finalized => genvm_modules_interfaces::On::Finalized, @@ -156,10 +212,13 @@ async fn consume_message_fee_internal( args: ConsumeInternalArgs, ) -> Result { validate_internal_price_caps(&fee_params)?; - let mut fee_cost = shared_data - .data_fees_limit - .calculate_message_fee_internal(&fee_params) - .map_err(internal_trap)?; + let mut fee_cost = match &funding { + FeeFunding::Allocation { .. } => shared_data + .data_fees_limit + .calculate_message_fee_internal(&fee_params) + .map_err(internal_trap)?, + FeeFunding::Balance { fee_cost, .. } => fee_cost.clone(), + }; if let FeeFunding::Allocation { node, .. } = &funding { let declared_budget = fee_cost @@ -244,6 +303,7 @@ async fn consume_message_fee_internal( value, messages_value_decremented, my_balance, + .. } => { // `value + fee_total` can itself overflow U256. let Some(total) = value.checked_add(fee_total) else { @@ -398,11 +458,11 @@ async fn consume_external_receipt_only( /// Magnitude bounds (in significant bits; a larger field is rejected) on /// guest-supplied fee params. Invariant the code cannot express: the worst-case /// `messageFeeFloor` result must stay within U256, since the fee evaluator's -/// `rational_to_u256` treats overflow as an internal abort. Three guest fields +/// `rational_to_u256` saturates overflow. Three guest fields /// multiply into one floor term (`maxPrice × rotations entry × validatorTU`), /// so with the default 18-round validator table (counts ≤ 1537 < 2^11) the /// worst case is -/// price(<2^96) × rounds(<2^5) × rot(<2^33) +/// price(<2^96) × rounds(<2^5) × rot(<2^32) /// × (leaderTU + vpr × validatorTU)(<2^44) /// + price(<2^96) × leaderRounds(<2^36) /// < 2^183 ≪ 2^256. @@ -411,13 +471,39 @@ async fn consume_external_receipt_only( pub(super) const FEE_PARAM_PRICE_BITS: usize = 96; pub(super) const FEE_PARAM_COUNT_BITS: usize = 32; +fn internal_price_caps_valid(params: &abi::fees::InternalMessageParams) -> bool { + !params.max_price_gen_per_time_unit.is_zero() + && !params.storage_fee_max_gas_price.is_zero() + && !params.receipt_fee_max_gas_price.is_zero() +} + +pub(super) fn internal_params_valid(params: &abi::fees::InternalMessageParams) -> bool { + // Transaction-pinned time-unit bounds and budget floor are not in host input yet. + if params.rotations.is_empty() || !internal_price_caps_valid(params) { + return false; + } + + let time_units_are_valid = (params.leader_time_units_allocation.is_zero() + && params.validator_time_units_allocation.is_zero()) + || (!params.leader_time_units_allocation.is_zero() + && !params.validator_time_units_allocation.is_zero()); + time_units_are_valid + && params.max_price_gen_per_time_unit.bits() <= FEE_PARAM_PRICE_BITS + && params.storage_fee_max_gas_price.bits() <= FEE_PARAM_PRICE_BITS + && params.receipt_fee_max_gas_price.bits() <= FEE_PARAM_PRICE_BITS + && params.execution_budget_per_round.bits() <= FEE_PARAM_PRICE_BITS + && params.leader_time_units_allocation.bits() <= FEE_PARAM_COUNT_BITS + && params.validator_time_units_allocation.bits() <= FEE_PARAM_COUNT_BITS + && params + .rotations + .iter() + .all(|rotation| rotation.bits() <= FEE_PARAM_COUNT_BITS) +} + fn validate_internal_price_caps( params: &abi::fees::InternalMessageParams, ) -> Result<(), generated::types::Error> { - if params.max_price_gen_per_time_unit.is_zero() - || params.storage_fee_max_gas_price.is_zero() - || params.receipt_fee_max_gas_price.is_zero() - { + if !internal_price_caps_valid(params) { log_debug!("internal message rejected: zero price cap (Inval)"); return Err(generated::types::Errno::Inval.into()); } @@ -434,8 +520,9 @@ fn validate_internal_price_caps( /// reveal: `rotations` must be non-empty (the yaml floor derives /// `appealRounds = len - 1` and would go negative otherwise), the three /// price caps must be non-zero (the chain reverts `FeeValueMustBeNonZero(4/5/6)` -/// at reveal), and every numeric field -- rotations entries included -- is -/// bounded by [`FEE_PARAM_PRICE_BITS`] / [`FEE_PARAM_COUNT_BITS`] so the +/// at reveal), leader and validator time units must be either both zero or both +/// non-zero, and every numeric field -- rotations entries included -- is +/// bounded by `FEE_PARAM_PRICE_BITS` / `FEE_PARAM_COUNT_BITS` so the /// metered floor fits in U256. The rotations-length upper bound is /// node-config-dependent (validator table length) and is enforced in the yaml /// fee expression instead. @@ -455,23 +542,8 @@ pub(super) fn validate_balance_fee( Err(generated::types::Errno::Inval.into()) } (true, Some(params)) => { - if params.rotations.is_empty() { - log_debug!("balance-funded message rejected: rotations empty (Inval)"); - return Err(generated::types::Errno::Inval.into()); - } - validate_internal_price_caps(¶ms)?; - let too_large = params.max_price_gen_per_time_unit.bits() > FEE_PARAM_PRICE_BITS - || params.storage_fee_max_gas_price.bits() > FEE_PARAM_PRICE_BITS - || params.receipt_fee_max_gas_price.bits() > FEE_PARAM_PRICE_BITS - || params.execution_budget_per_round.bits() > FEE_PARAM_PRICE_BITS - || params.leader_time_units_allocation.bits() > FEE_PARAM_COUNT_BITS - || params.validator_time_units_allocation.bits() > FEE_PARAM_COUNT_BITS - || params - .rotations - .iter() - .any(|r| r.bits() > FEE_PARAM_COUNT_BITS); - if too_large { - log_debug!("balance-funded message rejected: fee param too large (Inval)"); + if !internal_params_valid(¶ms) { + log_debug!("balance-funded message rejected: invalid fee params (Inval)"); return Err(generated::types::Errno::Inval.into()); } Ok(Some(params)) @@ -489,6 +561,15 @@ pub(super) struct EmitInternalDeployMessageArgs { pub value: primitive_types::U256, pub salt_nonce: primitive_types::U256, pub use_balance: bool, + pub descendants: Option, +} + +pub(super) struct EmitInternalMessageArgs { + pub value: primitive_types::U256, + pub on: gl_call::On, + pub use_balance: bool, + pub fee_params: Option, + pub descendants: Option, } impl ContextVFS<'_> { @@ -739,11 +820,15 @@ impl ContextVFS<'_> { &mut self, address: calldata::Address, calldata: abi::entry::MainCallData, - value: primitive_types::U256, - on: gl_call::On, - use_balance: bool, - fee_params: Option, + args: EmitInternalMessageArgs, ) -> Result { + let EmitInternalMessageArgs { + value, + on, + use_balance, + fee_params, + descendants, + } = args; log_debug!( recipient = address, on:? = on, @@ -768,6 +853,11 @@ impl ContextVFS<'_> { use_balance, fee_params, )?; + let grant = prepare_grant( + &self.context.data.supervisor.shared_data.data_fees_limit, + balance_params.as_ref(), + descendants, + )?; let is_first_message = next_message_is_first(&self.context.data.accumulator.emissions); let call_key = if let Some(method_name) = &calldata.name { @@ -777,6 +867,11 @@ impl ContextVFS<'_> { }; if let Some(params) = balance_params { + let fee_cost = balance_fee_cost( + &self.context.data.supervisor.shared_data.data_fees_limit, + ¶ms, + grant.budget, + )?; let mut enc = calldata::Encoder::new(calldata::CounterWriter(0)); calldata::codec::Encode::encode(&calldata, &mut enc).unwrap_or_else(|e| match e {}); let calldata_length = enc.into_inner().0; @@ -784,7 +879,11 @@ impl ContextVFS<'_> { .saturating_mul(memory_limiter_consts::MESSAGE_FEE_ROTATION_ELEMENT_SIZE.into()); let allocation = reserve_permanent( &self.context.limiter, - emission_allocation_size(&[calldata_length, rotations_size]), + emission_allocation_size(&[ + calldata_length, + rotations_size, + grant.subtree.len().into_int_comptime(), + ]), "internal message", )?; @@ -801,6 +900,7 @@ impl ContextVFS<'_> { value, messages_value_decremented, my_balance, + fee_cost, }, Arc::new(params.clone()), ConsumeInternalArgs { @@ -808,14 +908,13 @@ impl ContextVFS<'_> { is_deploy: false, calldata_length, code_length: 0, - subtree_length: 0, + subtree_length: grant.subtree.len().into_int_comptime(), }, ) .await?; - let metered_fee = fees.message_fee.reported_fee(); + let declared_budget = fees.message_fee.reported_fee(); - // Empty subtree: use_balance nesting is fail-closed on-chain. self.context.data.accumulator.emissions.push( domain::ExecutionEmission::InternalMessage { call_key, @@ -823,10 +922,10 @@ impl ContextVFS<'_> { calldata, value, on, - message_fee: metered_fee, + message_fee: declared_budget, receipt_fee: fees.receipt_fee.reported_fee(), fee_params: params, - subtree: bytes::Bytes::new(), + subtree: grant.subtree.into(), use_balance: true, }, ); @@ -834,7 +933,7 @@ impl ContextVFS<'_> { self.context.data.accumulator.messages_value_decremented = messages_value_decremented .saturating_add(value) - .saturating_add(metered_fee); + .saturating_add(declared_budget); return Ok(file_fd_none()); } @@ -964,6 +1063,7 @@ impl ContextVFS<'_> { value, salt_nonce, use_balance, + descendants, } = args; if !self.context.data.conf.permissions.deterministic { @@ -982,9 +1082,19 @@ impl ContextVFS<'_> { use_balance, fee_params, )?; + let grant = prepare_grant( + &self.context.data.supervisor.shared_data.data_fees_limit, + balance_params.as_ref(), + descendants, + )?; let is_first_message = next_message_is_first(&self.context.data.accumulator.emissions); if let Some(params) = balance_params { + let fee_cost = balance_fee_cost( + &self.context.data.supervisor.shared_data.data_fees_limit, + ¶ms, + grant.budget, + )?; let code_length = code.len().into_int_comptime(); let mut enc = calldata::Encoder::new(calldata::CounterWriter(0)); calldata::codec::Encode::encode(&calldata, &mut enc).unwrap_or_else(|e| match e {}); @@ -993,7 +1103,12 @@ impl ContextVFS<'_> { .saturating_mul(memory_limiter_consts::MESSAGE_FEE_ROTATION_ELEMENT_SIZE.into()); let allocation = reserve_permanent( &self.context.limiter, - emission_allocation_size(&[calldata_length, code_length, rotations_size]), + emission_allocation_size(&[ + calldata_length, + code_length, + rotations_size, + grant.subtree.len().into_int_comptime(), + ]), "internal deploy message", )?; @@ -1010,6 +1125,7 @@ impl ContextVFS<'_> { value, messages_value_decremented, my_balance, + fee_cost, }, Arc::new(params.clone()), ConsumeInternalArgs { @@ -1017,12 +1133,12 @@ impl ContextVFS<'_> { is_deploy: true, calldata_length, code_length, - subtree_length: 0, + subtree_length: grant.subtree.len().into_int_comptime(), }, ) .await?; - let metered_fee = fees.message_fee.reported_fee(); + let declared_budget = fees.message_fee.reported_fee(); self.context.data.accumulator.emissions.push( domain::ExecutionEmission::InternalDeployMessage { @@ -1032,9 +1148,9 @@ impl ContextVFS<'_> { on, salt_nonce, receipt_fee: fees.receipt_fee.reported_fee(), - message_fee: metered_fee, + message_fee: declared_budget, fee_params: params, - subtree: bytes::Bytes::new(), + subtree: grant.subtree.into(), use_balance: true, }, ); @@ -1042,7 +1158,7 @@ impl ContextVFS<'_> { self.context.data.accumulator.messages_value_decremented = messages_value_decremented .saturating_add(value) - .saturating_add(metered_fee); + .saturating_add(declared_budget); return Ok(file_fd_none()); } diff --git a/executor/src/wasi/genlayer_sdk/mod.rs b/executor/src/wasi/genlayer_sdk/mod.rs index 0cfac600..9e410fe4 100644 --- a/executor/src/wasi/genlayer_sdk/mod.rs +++ b/executor/src/wasi/genlayer_sdk/mod.rs @@ -17,6 +17,7 @@ use genlayer_sdk::abi::{self, gl_call}; use super::{base, vfs}; +mod descendant_grant; mod message; mod run; #[cfg(test)] @@ -524,7 +525,7 @@ fn slot_access_fits(index: u32, buf_len: u32) -> bool { u64::from(index) + u64::from(buf_len) <= rt::vm::storage::SLOT_SIZE } -use message::EmitInternalDeployMessageArgs; +use message::{EmitInternalDeployMessageArgs, EmitInternalMessageArgs}; #[allow(unused_variables)] impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { @@ -582,14 +583,18 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { on, use_balance, fee_params, + descendants, } => { self.gl_call_emit_internal_message( address, calldata, - value, - on, - use_balance, - fee_params, + EmitInternalMessageArgs { + value, + on, + use_balance, + fee_params, + descendants, + }, ) .await } @@ -601,6 +606,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { salt_nonce, use_balance, fee_params, + descendants, } => { self.gl_call_emit_internal_deploy_message( calldata, @@ -611,6 +617,7 @@ impl generated::genlayer_sdk::GenlayerSdk for ContextVFS<'_> { value, salt_nonce, use_balance, + descendants, }, ) .await diff --git a/executor/src/wasi/genlayer_sdk/testdata/descendant-grant-vectors.json b/executor/src/wasi/genlayer_sdk/testdata/descendant-grant-vectors.json new file mode 100644 index 00000000..3ade5869 --- /dev/null +++ b/executor/src/wasi/genlayer_sdk/testdata/descendant-grant-vectors.json @@ -0,0 +1,359 @@ +{ + "schemaVersion": 1, + "purpose": "Portable canonical ABI conformance vectors for GenVM/node producers and consensus consumers.", + "generator": "scripts/utils/generateContractDescendantGrantVectors.ts", + "encoding": { + "operation": "abi.encode(bytes32 domain, ContractDescendantGrant grant)", + "abiTypes": [ + "bytes32", + "tuple(uint8 version, uint8 policy, uint256 budget, tuple(uint8 messageType, bool onAcceptance, uint256 parentIndex, address recipient, bytes32 callKey, uint256 budget, bytes feeParams)[] allocations)" + ], + "domainText": "genlayer.contract-descendant-grant", + "domainHex": "0x5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb", + "version": "1", + "policies": { + "Closed": "0", + "Open": "1", + "Pinned": "2" + }, + "messageTypes": { + "External": "0", + "Internal": "1" + }, + "rootParentIndex": "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "integerEncoding": "All decoded ABI integers are unsigned decimal strings; sizes/counts outside decoded ABI objects are JSON numbers.", + "internalFeeParamsAbiType": "tuple(uint256 leaderTimeunitsAllocation, uint256 validatorTimeunitsAllocation, uint256 appealRounds, uint256 executionBudgetPerRound, uint256[] rotations, uint256 maxPriceGenPerTimeUnit, uint256 storageFeeMaxGasPrice, uint256 receiptFeeMaxGasPrice)", + "externalFeeParamsAbiType": "tuple(uint256 gasLimit, uint256 maxGasPrice)", + "submittedMessagesAbiType": "tuple(uint8 messageType, address recipient, uint256 value, bytes data, bool onAcceptance, uint256 saltNonce, bytes feeParams, uint256 declaredBudget, bytes allocationSubtree, bytes32 callKey, bool useBalance)[]" + }, + "validationNotes": [ + "Valid vectors are canonical and satisfy policy/tree-shape/root-sum rules. Full economic admission still depends on the emitting parent's pinned admission and fee policy; obtain its actual primary quote from minMessagePrimaryFeesForTx.", + "Declared-budget examples use an assumed primary quote to show B = P + D + surplus; producers must query minMessagePrimaryFeesForTx for the real P.", + "The mixed Pinned vector has two roots: internal index 0 and external index 2. Internal index 1 is nested and is not added to the root-budget sum again.", + "Unsupported enum policies fail Solidity ABI decoding; that failure is not normalized to InvalidContractDescendantGrant and no stable custom selector is asserted.", + "A wrong root-budget sum is ABI-valid and passes the codec. validateContractDescendantGrant rejects it during allocation admission with MessageAllocationsNotEqualBudget.", + "Legacy empty bytes decode as Closed, but keep the historical primary/remainder funding split. Explicit Closed reserves D = 0." + ], + "messageEnvelopeTemplate": { + "messageType": "1", + "recipient": "0x0000000000000000000000000000000000000011", + "value": "0", + "data": "0x1234", + "onAcceptance": false, + "saltNonce": "0", + "feeParams": "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "feeParamsDecoded": { + "leaderTimeunitsAllocation": "5", + "validatorTimeunitsAllocation": "10", + "appealRounds": "0", + "executionBudgetPerRound": "100000000000000000", + "rotations": ["0"], + "maxPriceGenPerTimeUnit": "1", + "storageFeeMaxGasPrice": "1000000000000000000", + "receiptFeeMaxGasPrice": "1000000000000000000" + }, + "declaredBudget": "Use each vector's declaredBudgetExample.declaredBudget.", + "allocationSubtree": "Use each vector's payloadHex.", + "callKey": "0x0000000000000000000000000000000000000000000000000000000000000000", + "useBalance": true + }, + "validVectors": [ + { + "name": "closed-explicit", + "description": "Explicit Closed with no descendant allowance.", + "wireForm": "explicit-v1", + "payloadHex": "0x5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "payloadBytes": 224, + "payloadKeccak256": "0x406f5f74fd9c19c37478c7833fb1cd5a5bf63e9fe49e7f969b52e01afc52573d", + "decodedGrant": { + "version": "1", + "policy": "0", + "budget": "0", + "allocations": [] + }, + "allocationFeeParamsDecoded": [], + "declaredBudgetExample": { + "assumedChildPrimaryQuote": "1000000000000000000", + "descendantBudget": "0", + "primarySurplus": "50000000000000000", + "declaredBudget": "1050000000000000000" + }, + "messageEnvelopeExample": { + "messageCount": 1, + "messageBytes": 1152, + "otherExecutionFieldsHash": "0x52b84d6916a4f240b6043dd68c42ed44b1a832d8d873e6c072237805bea42ab3", + "messagesAndOtherFieldsHash": "0xa4aad112d61ef09a925fe9658b9c21b10ed1611e999c22ecd820efc2bd53f0a5" + } + }, + { + "name": "open-explicit", + "description": "Open descendants within an explicit contract-funded bucket.", + "wireForm": "explicit-v1", + "payloadHex": "0x5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000429d069189e000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "payloadBytes": 224, + "payloadKeccak256": "0x3bfb47b06c42438373ee95ee5b4818d37fd8042319ee42a46ef5fac6df0cef68", + "decodedGrant": { + "version": "1", + "policy": "1", + "budget": "300000000000000000", + "allocations": [] + }, + "allocationFeeParamsDecoded": [], + "declaredBudgetExample": { + "assumedChildPrimaryQuote": "1000000000000000000", + "descendantBudget": "300000000000000000", + "primarySurplus": "50000000000000000", + "declaredBudget": "1350000000000000000" + }, + "messageEnvelopeExample": { + "messageCount": 1, + "messageBytes": 1152, + "otherExecutionFieldsHash": "0x52b84d6916a4f240b6043dd68c42ed44b1a832d8d873e6c072237805bea42ab3", + "messagesAndOtherFieldsHash": "0x917452fd08a49090889f3b098bd1e8b83be256a31c823a9df41ddb13a7250bbf" + } + }, + { + "name": "pinned-single-internal", + "description": "One allowed internal descendant; the node is already a direct child root.", + "wireForm": "explicit-v1", + "payloadHex": "0x5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000429d069189e000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000429d069189e000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "payloadBytes": 864, + "payloadKeccak256": "0x07669715194cf1db8fbc1b70d6e4aa91fa9df21305a7eed1570c50112a74f47d", + "decodedGrant": { + "version": "1", + "policy": "2", + "budget": "300000000000000000", + "allocations": [ + { + "messageType": "1", + "onAcceptance": false, + "parentIndex": "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "recipient": "0x0000000000000000000000000000000000000011", + "callKey": "0x0000000000000000000000000000000000000000000000000000000000000000", + "budget": "300000000000000000", + "feeParams": "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + } + ] + }, + "allocationFeeParamsDecoded": [ + { + "allocationIndex": "0", + "type": "InternalMessageFeeParams", + "fields": { + "leaderTimeunitsAllocation": "5", + "validatorTimeunitsAllocation": "10", + "appealRounds": "0", + "executionBudgetPerRound": "100000000000000000", + "rotations": ["0"], + "maxPriceGenPerTimeUnit": "1", + "storageFeeMaxGasPrice": "1000000000000000000", + "receiptFeeMaxGasPrice": "1000000000000000000" + } + } + ], + "declaredBudgetExample": { + "assumedChildPrimaryQuote": "1000000000000000000", + "descendantBudget": "300000000000000000", + "primarySurplus": "50000000000000000", + "declaredBudget": "1350000000000000000" + }, + "messageEnvelopeExample": { + "messageCount": 1, + "messageBytes": 1792, + "otherExecutionFieldsHash": "0x52b84d6916a4f240b6043dd68c42ed44b1a832d8d873e6c072237805bea42ab3", + "messagesAndOtherFieldsHash": "0x7aa050654167f81db28269d6b8c91c0103533f9603e914ad99c8ddc35adc18b0" + } + }, + { + "name": "pinned-nested-internal-and-external-root", + "description": "An internal root and its internal child, plus a separate external root allocation.", + "wireForm": "explicit-v1", + "payloadHex": "0x5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000085456b85230800000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000853a0d2313c000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c68af0bb14000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000033b9ee2e14f00c68d60911d6c13db158044bd494f772f7785c2f108fdeb2949f810000000000000000000000000000000000000000000000000000b5e620f4800000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000030d40000000000000000000000000000000000000000000000000000000003b9aca00", + "payloadBytes": 1856, + "payloadKeccak256": "0xcb946323c2548d70c2511cfcdd74564e0ebb7fa19610a2a379d9aebd4037882d", + "decodedGrant": { + "version": "1", + "policy": "2", + "budget": "600200000000000000", + "allocations": [ + { + "messageType": "1", + "onAcceptance": false, + "parentIndex": "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "recipient": "0x0000000000000000000000000000000000000011", + "callKey": "0x0000000000000000000000000000000000000000000000000000000000000000", + "budget": "600000000000000000", + "feeParams": "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + }, + { + "messageType": "1", + "onAcceptance": true, + "parentIndex": "0", + "recipient": "0x0000000000000000000000000000000000000022", + "callKey": "0x0000000000000000000000000000000000000000000000000000000000000000", + "budget": "200000000000000000", + "feeParams": "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + }, + { + "messageType": "0", + "onAcceptance": false, + "parentIndex": "115792089237316195423570985008687907853269984665640564039457584007913129639935", + "recipient": "0x0000000000000000000000000000000000000033", + "callKey": "0xb9ee2e14f00c68d60911d6c13db158044bd494f772f7785c2f108fdeb2949f81", + "budget": "200000000000000", + "feeParams": "0x0000000000000000000000000000000000000000000000000000000000030d40000000000000000000000000000000000000000000000000000000003b9aca00" + } + ] + }, + "allocationFeeParamsDecoded": [ + { + "allocationIndex": "0", + "type": "InternalMessageFeeParams", + "fields": { + "leaderTimeunitsAllocation": "5", + "validatorTimeunitsAllocation": "10", + "appealRounds": "0", + "executionBudgetPerRound": "100000000000000000", + "rotations": ["0"], + "maxPriceGenPerTimeUnit": "1", + "storageFeeMaxGasPrice": "1000000000000000000", + "receiptFeeMaxGasPrice": "1000000000000000000" + } + }, + { + "allocationIndex": "1", + "type": "InternalMessageFeeParams", + "fields": { + "leaderTimeunitsAllocation": "5", + "validatorTimeunitsAllocation": "10", + "appealRounds": "0", + "executionBudgetPerRound": "100000000000000000", + "rotations": ["0"], + "maxPriceGenPerTimeUnit": "1", + "storageFeeMaxGasPrice": "1000000000000000000", + "receiptFeeMaxGasPrice": "1000000000000000000" + } + }, + { + "allocationIndex": "2", + "type": "ExternalMessageFeeParams", + "fields": { + "gasLimit": "200000", + "maxGasPrice": "1000000000" + } + } + ], + "declaredBudgetExample": { + "assumedChildPrimaryQuote": "1000000000000000000", + "descendantBudget": "600200000000000000", + "primarySurplus": "50000000000000000", + "declaredBudget": "1650200000000000000" + }, + "messageEnvelopeExample": { + "messageCount": 1, + "messageBytes": 2784, + "otherExecutionFieldsHash": "0x52b84d6916a4f240b6043dd68c42ed44b1a832d8d873e6c072237805bea42ab3", + "messagesAndOtherFieldsHash": "0xa8aafb2cb5096d3095bc63750066b693028fddfb855a8669fc194253c9ae1623" + } + }, + { + "name": "closed-legacy-omitted", + "description": "Backward-compatible omitted grant bytes.", + "wireForm": "legacy-empty", + "payloadHex": "0x", + "payloadBytes": 0, + "payloadKeccak256": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "decodedGrant": { + "version": "1", + "policy": "0", + "budget": "0", + "allocations": [] + }, + "allocationFeeParamsDecoded": [], + "declaredBudgetExample": { + "assumedChildPrimaryQuote": "1000000000000000000", + "descendantBudget": "0", + "primarySurplus": "0", + "declaredBudget": "1000000000000000000" + }, + "messageEnvelopeExample": { + "messageCount": 1, + "messageBytes": 928, + "otherExecutionFieldsHash": "0x52b84d6916a4f240b6043dd68c42ed44b1a832d8d873e6c072237805bea42ab3", + "messagesAndOtherFieldsHash": "0x5897a2cb1a1fe22c557dd21667a83d7c41fc0d561f86941a7a15820110844d88" + } + } + ], + "negativeVectors": [ + { + "name": "wrong-domain", + "sourceValidVector": "closed-explicit", + "payloadHex": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "payloadBytes": 224, + "payloadKeccak256": "0x25d5f9edaf186d36f4535411026599b194b7e100e08c033fccfca7fb3e30bc76", + "expected": { + "category": "wrong-domain", + "rejectionStage": "codec", + "codecAccepts": false, + "error": "InvalidContractDescendantGrant", + "errorSelector": "0xde09fce7" + } + }, + { + "name": "unsupported-version", + "sourceValidVector": "closed-explicit", + "payloadHex": "0x5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "payloadBytes": 224, + "payloadKeccak256": "0x91ffe59236dc851a43f0b9f27b4cd7b88c70b4ad78d65ba68d3bf1df7c7cbd81", + "expected": { + "category": "unsupported-version", + "rejectionStage": "codec", + "codecAccepts": false, + "error": "InvalidContractDescendantGrant", + "errorSelector": "0xde09fce7" + } + }, + { + "name": "trailing-bytes", + "sourceValidVector": "closed-explicit", + "payloadHex": "0x5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000", + "payloadBytes": 225, + "payloadKeccak256": "0x7cbc72569df1403a8613f9f5d80379a3a9e750fdef4583d39b14e5733241f4f3", + "expected": { + "category": "noncanonical-encoding", + "rejectionStage": "codec", + "codecAccepts": false, + "error": "InvalidContractDescendantGrant", + "errorSelector": "0xde09fce7" + } + }, + { + "name": "unsupported-policy", + "sourceValidVector": "closed-explicit", + "payloadHex": "0x5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "payloadBytes": 224, + "payloadKeccak256": "0xe81ba3ca0d515bd91b92c1d2fc3800f26dee33cfb787cdf40407d6af00778ed4", + "expected": { + "category": "invalid-enum-discriminant", + "rejectionStage": "codec", + "codecAccepts": false, + "error": null, + "errorSelector": null + } + }, + { + "name": "pinned-root-budget-mismatch", + "sourceValidVector": "pinned-single-internal", + "payloadHex": "0x5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000429d069189e000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000429d069189e000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "payloadBytes": 864, + "payloadKeccak256": "0xd25c93ea4c46dcf64d6c34fd686f3d309008ba9e8b01efed9980500b2fc23bf2", + "expected": { + "category": "root-budget-sum-mismatch", + "rejectionStage": "allocation-admission", + "codecAccepts": true, + "error": "MessageAllocationsNotEqualBudget", + "errorSelector": "0x9659e275" + } + } + ] +} diff --git a/executor/src/wasi/genlayer_sdk/tests.rs b/executor/src/wasi/genlayer_sdk/tests.rs index 98feca33..e592dda0 100644 --- a/executor/src/wasi/genlayer_sdk/tests.rs +++ b/executor/src/wasi/genlayer_sdk/tests.rs @@ -1,3 +1,7 @@ +use super::descendant_grant::{ + encode_grant, prepare_descendants, AllocationFeeParams, FlatAllocation, Grant, GrantPolicy, + GrantValidationError, ROOT_PARENT, +}; use super::message::{ external_allocation_candidates, next_message_is_first, resolve_internal_allocation, validate_balance_fee, FEE_PARAM_COUNT_BITS, FEE_PARAM_PRICE_BITS, @@ -26,6 +30,499 @@ fn valid_params() -> abi::fees::InternalMessageParams { } } +fn grant_params() -> abi::fees::InternalMessageParams { + abi::fees::InternalMessageParams { + leader_time_units_allocation: U256::from(5), + validator_time_units_allocation: U256::from(10), + execution_budget_per_round: U256::from_dec_str("100000000000000000").unwrap(), + rotations: vec![U256::zero()], + max_price_gen_per_time_unit: U256::one(), + storage_fee_max_gas_price: U256::from_dec_str("1000000000000000000").unwrap(), + receipt_fee_max_gas_price: U256::from_dec_str("1000000000000000000").unwrap(), + } +} + +fn grant_address(last: u8) -> calldata::Address { + let mut raw = [0; 20]; + raw[19] = last; + calldata::Address::from(raw) +} + +fn vector_payload(name: &str) -> Vec { + let fixture: serde_json::Value = + serde_json::from_str(include_str!("testdata/descendant-grant-vectors.json")).unwrap(); + let payload = fixture["validVectors"] + .as_array() + .unwrap() + .iter() + .find(|vector| vector["name"] == name) + .unwrap()["payloadHex"] + .as_str() + .unwrap(); + hex::decode(payload.strip_prefix("0x").unwrap()).unwrap() +} + +fn internal_flat( + parent_index: U256, + last: u8, + budget: &str, + on_acceptance: bool, +) -> FlatAllocation { + FlatAllocation { + on_acceptance, + parent_index, + recipient: grant_address(last), + call_key: abi::CallKey::DEPLOY, + budget: U256::from_dec_str(budget).unwrap(), + fee_params: AllocationFeeParams::Internal(grant_params()), + } +} + +fn internal_allocation( + last: u8, + budget: u64, + on: gl_call::On, + parent_index: U256, +) -> gl_call::AllocationNode { + gl_call::AllocationNode::Internal(gl_call::InternalAllocation { + recipient: grant_address(last), + call_key: abi::CallKey::DEPLOY, + budget: U256::from(budget), + fee_params: grant_params(), + on, + parent_index, + }) +} + +fn external_allocation_node(budget: U256) -> gl_call::AllocationNode { + gl_call::AllocationNode::External(gl_call::ExternalAllocation { + parent_index: ROOT_PARENT, + recipient: grant_address(0x33), + call_key: abi::CallKey([7; 32]), + budget, + fee_params: abi::fees::ExternalMessageParams { + gas_limit: U256::from(20), + max_gas_price: U256::from(10), + }, + }) +} + +fn prepare( + descendants: Option, +) -> Result { + prepare_descendants(&grant_params(), descendants, |_| Ok(U256::from(10))) +} + +#[test] +fn descendant_grant_domain_matches_consensus_vector() { + use sha3::Digest as _; + + let expected = + hex::decode("5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb").unwrap(); + assert_eq!( + sha3::Keccak256::digest(b"genlayer.contract-descendant-grant").as_slice(), + expected + ); +} + +#[test] +fn descendant_grant_closed_and_open_match_vectors() { + let closed = Grant { + policy: GrantPolicy::Closed, + budget: U256::zero(), + allocations: vec![], + }; + assert_eq!(encode_grant(&closed), vector_payload("closed-explicit")); + + let open = Grant { + policy: GrantPolicy::Open, + budget: U256::from_dec_str("300000000000000000").unwrap(), + allocations: vec![], + }; + assert_eq!(encode_grant(&open), vector_payload("open-explicit")); +} + +#[test] +fn descendant_grant_single_internal_matches_vector() { + let grant = Grant { + policy: GrantPolicy::Pinned, + budget: U256::from_dec_str("300000000000000000").unwrap(), + allocations: vec![internal_flat( + ROOT_PARENT, + 0x11, + "300000000000000000", + false, + )], + }; + assert_eq!( + encode_grant(&grant), + vector_payload("pinned-single-internal") + ); +} + +#[test] +fn descendant_grant_nested_mixed_matches_vector() { + let mut call_key = [0; 32]; + call_key.copy_from_slice( + &hex::decode("b9ee2e14f00c68d60911d6c13db158044bd494f772f7785c2f108fdeb2949f81").unwrap(), + ); + let grant = Grant { + policy: GrantPolicy::Pinned, + budget: U256::from_dec_str("600200000000000000").unwrap(), + allocations: vec![ + internal_flat(ROOT_PARENT, 0x11, "600000000000000000", false), + internal_flat(U256::zero(), 0x22, "200000000000000000", true), + FlatAllocation { + on_acceptance: false, + parent_index: ROOT_PARENT, + recipient: grant_address(0x33), + call_key: abi::CallKey(call_key), + budget: U256::from_dec_str("200000000000000").unwrap(), + fee_params: AllocationFeeParams::External(abi::fees::ExternalMessageParams { + gas_limit: U256::from(200_000), + max_gas_price: U256::from(1_000_000_000), + }), + }, + ], + }; + assert_eq!( + encode_grant(&grant), + vector_payload("pinned-nested-internal-and-external-root") + ); +} + +#[test] +fn descendant_grant_closed_forms_emit_no_bytes() { + for descendants in [ + None, + Some(gl_call::Descendants::Open(U256::zero())), + Some(gl_call::Descendants::Pinned(vec![])), + ] { + let prepared = prepare(descendants).unwrap(); + assert_eq!(prepared.budget, U256::zero()); + assert!(prepared.subtree.is_empty()); + } +} + +#[test] +fn descendant_grant_rejects_more_than_twenty_four_nodes() { + let roots = (0..25) + .map(|last| internal_allocation(last, 10, gl_call::On::Finalized, ROOT_PARENT)) + .collect(); + let result = prepare(Some(gl_call::Descendants::Pinned(roots))); + assert!(matches!(result, Err(GrantValidationError::Tree))); +} + +#[test] +fn descendant_grant_accepts_a_twenty_four_node_chain() { + let nodes = (0..24u8) + .map(|index| { + internal_allocation( + index, + u64::from(24 - index) * 10, + gl_call::On::Finalized, + if index == 0 { + ROOT_PARENT + } else { + U256::from(index - 1) + }, + ) + }) + .collect(); + let prepared = prepare(Some(gl_call::Descendants::Pinned(nodes))).unwrap(); + assert_eq!(prepared.budget, U256::from(240)); +} + +#[test] +fn descendant_grant_rejects_duplicate_siblings_regardless_of_phase() { + let mut duplicate = match internal_allocation(1, 10, gl_call::On::Finalized, ROOT_PARENT) { + gl_call::AllocationNode::Internal(node) => node, + _ => unreachable!(), + }; + duplicate.on = gl_call::On::Decided; + let roots = vec![ + internal_allocation(1, 10, gl_call::On::Finalized, ROOT_PARENT), + gl_call::AllocationNode::Internal(duplicate), + ]; + let result = prepare(Some(gl_call::Descendants::Pinned(roots))); + assert!(matches!(result, Err(GrantValidationError::Tree))); +} + +#[test] +fn descendant_grant_rejects_external_child() { + let root = internal_allocation(1, 210, gl_call::On::Finalized, ROOT_PARENT); + let mut child = external_allocation_node(U256::from(200)); + let gl_call::AllocationNode::External(node) = &mut child else { + unreachable!() + }; + node.parent_index = U256::zero(); + let result = prepare(Some(gl_call::Descendants::Pinned(vec![root, child]))); + assert!(matches!(result, Err(GrantValidationError::Tree))); +} + +#[test] +fn descendant_grant_rejects_self_forward_and_out_of_range_parents() { + for parent_index in [U256::zero(), U256::one(), U256::MAX - U256::one()] { + let result = prepare(Some(gl_call::Descendants::Pinned(vec![ + internal_allocation(1, 10, gl_call::On::Finalized, parent_index), + ]))); + assert!( + matches!(result, Err(GrantValidationError::Tree)), + "unexpected result: {result:?}" + ); + } +} + +#[test] +fn descendant_grant_rejects_children_of_external_nodes() { + let result = prepare(Some(gl_call::Descendants::Pinned(vec![ + external_allocation_node(U256::from(200)), + internal_allocation(1, 10, gl_call::On::Finalized, U256::zero()), + ]))); + assert!( + matches!(result, Err(GrantValidationError::Tree)), + "unexpected result: {result:?}" + ); +} + +#[test] +fn descendant_grant_preserves_non_preorder_indices() { + let nodes = vec![ + internal_allocation(1, 20, gl_call::On::Finalized, ROOT_PARENT), + external_allocation_node(U256::from(200)), + internal_allocation(2, 10, gl_call::On::Finalized, U256::zero()), + ]; + let prepared = prepare(Some(gl_call::Descendants::Pinned(nodes))).unwrap(); + let expected = Grant { + policy: GrantPolicy::Pinned, + budget: U256::from(220), + allocations: vec![ + internal_flat(ROOT_PARENT, 1, "20", false), + FlatAllocation { + on_acceptance: false, + parent_index: ROOT_PARENT, + recipient: grant_address(0x33), + call_key: abi::CallKey([7; 32]), + budget: U256::from(200), + fee_params: AllocationFeeParams::External(abi::fees::ExternalMessageParams { + gas_limit: U256::from(20), + max_gas_price: U256::from(10), + }), + }, + internal_flat(U256::zero(), 2, "10", false), + ], + }; + assert_eq!(prepared.subtree, encode_grant(&expected)); +} + +#[test] +fn descendant_grant_rejects_invalid_internal_fee_shapes() { + let mut invalid = grant_params(); + invalid.leader_time_units_allocation = U256::zero(); + let gl_call::AllocationNode::Internal(mut node) = + internal_allocation(1, 10, gl_call::On::Finalized, ROOT_PARENT) + else { + unreachable!() + }; + node.fee_params = invalid; + let result = prepare(Some(gl_call::Descendants::Pinned(vec![ + gl_call::AllocationNode::Internal(node), + ]))); + assert!(matches!(result, Err(GrantValidationError::Inval))); + + let gl_call::AllocationNode::Internal(mut oversized) = + internal_allocation(1, 10, gl_call::On::Finalized, ROOT_PARENT) + else { + unreachable!() + }; + oversized.fee_params.rotations = vec![U256::zero(); 23]; + let result = prepare(Some(gl_call::Descendants::Pinned(vec![ + gl_call::AllocationNode::Internal(oversized), + ]))); + assert!(matches!(result, Err(GrantValidationError::Inval))); +} + +#[test] +fn descendant_grant_accepts_twenty_two_rotations_and_rejects_twenty_three() { + let make_root = |rotation_count| { + let gl_call::AllocationNode::Internal(mut node) = + internal_allocation(1, 10, gl_call::On::Finalized, ROOT_PARENT) + else { + unreachable!() + }; + node.fee_params.rotations = vec![U256::zero(); rotation_count]; + gl_call::AllocationNode::Internal(node) + }; + + prepare(Some(gl_call::Descendants::Pinned(vec![make_root(22)]))).unwrap(); + let result = prepare(Some(gl_call::Descendants::Pinned(vec![make_root(23)]))); + assert!(matches!(result, Err(GrantValidationError::Inval))); +} + +#[test] +fn descendant_grant_rejects_zero_budget_nodes_at_any_depth() { + let cases = [ + vec![internal_allocation( + 1, + 0, + gl_call::On::Finalized, + ROOT_PARENT, + )], + vec![external_allocation_node(U256::zero())], + vec![ + internal_allocation(1, 10, gl_call::On::Finalized, ROOT_PARENT), + internal_allocation(2, 0, gl_call::On::Finalized, U256::zero()), + ], + ]; + + for nodes in cases { + let result = prepare(Some(gl_call::Descendants::Pinned(nodes))); + assert!(matches!(result, Err(GrantValidationError::Budget))); + } +} + +#[test] +fn descendant_grant_rejects_invalid_external_budget() { + let zero = prepare(Some(gl_call::Descendants::Pinned(vec![ + external_allocation_node(U256::zero()), + ]))); + assert!(matches!(zero, Err(GrantValidationError::Budget))); + + for budget in [U256::from(199), U256::MAX] { + let result = prepare(Some(gl_call::Descendants::Pinned(vec![ + external_allocation_node(budget), + ]))); + assert!(matches!(result, Err(GrantValidationError::External))); + } +} + +#[test] +fn descendant_grant_rejects_insufficient_internal_budget() { + let result = prepare(Some(gl_call::Descendants::Pinned(vec![ + internal_allocation(1, 9, gl_call::On::Finalized, ROOT_PARENT), + ]))); + assert!(matches!(result, Err(GrantValidationError::Budget))); +} + +#[test] +fn descendant_grant_accepts_exact_required_internal_budget() { + let prepared = prepare(Some(gl_call::Descendants::Pinned(vec![ + internal_allocation(1, 10, gl_call::On::Finalized, ROOT_PARENT), + ]))) + .unwrap(); + assert_eq!(prepared.budget, U256::from(10)); +} + +#[test] +fn descendant_grant_allows_the_same_key_under_different_parents() { + let roots = vec![ + internal_allocation(1, 20, gl_call::On::Finalized, ROOT_PARENT), + internal_allocation(2, 20, gl_call::On::Finalized, ROOT_PARENT), + internal_allocation(3, 10, gl_call::On::Finalized, U256::zero()), + internal_allocation(3, 10, gl_call::On::Finalized, U256::one()), + ]; + + let prepared = prepare(Some(gl_call::Descendants::Pinned(roots))).unwrap(); + assert_eq!(prepared.budget, U256::from(40)); +} + +#[test] +fn descendant_grant_decided_root_uses_enclosing_appeal_multiplier() { + let mut enclosing = grant_params(); + enclosing.rotations.push(U256::zero()); + let descendants = Some(gl_call::Descendants::Pinned(vec![internal_allocation( + 1, + 19, + gl_call::On::Decided, + ROOT_PARENT, + )])); + let result = prepare_descendants(&enclosing, descendants, |_| Ok(U256::from(10))); + assert!(matches!(result, Err(GrantValidationError::Budget))); +} + +#[test] +fn descendant_grant_budget_is_sum_of_roots_and_payload_is_bounded() { + let roots = (0..24) + .map(|last| { + let mut node = match internal_allocation(last, 10, gl_call::On::Finalized, ROOT_PARENT) + { + gl_call::AllocationNode::Internal(node) => node, + _ => unreachable!(), + }; + node.fee_params.rotations = vec![U256::zero(); 22]; + gl_call::AllocationNode::Internal(node) + }) + .collect(); + let prepared = prepare(Some(gl_call::Descendants::Pinned(roots))).unwrap(); + assert_eq!(prepared.budget, U256::from(240)); + assert_eq!(prepared.subtree.len(), 31_712); +} + +#[test] +fn descendant_grant_rejects_budget_arithmetic_overflow() { + let gl_call::AllocationNode::Internal(mut max_root) = + internal_allocation(1, 1, gl_call::On::Finalized, ROOT_PARENT) + else { + unreachable!() + }; + max_root.budget = U256::MAX; + let root_sum = prepare(Some(gl_call::Descendants::Pinned(vec![ + gl_call::AllocationNode::Internal(max_root), + internal_allocation(2, 1, gl_call::On::Finalized, ROOT_PARENT), + ]))); + assert!(matches!(root_sum, Err(GrantValidationError::Budget))); + + let child = internal_allocation(2, 1, gl_call::On::Finalized, U256::zero()); + let gl_call::AllocationNode::Internal(mut parent) = + internal_allocation(1, 1, gl_call::On::Finalized, ROOT_PARENT) + else { + unreachable!() + }; + parent.budget = U256::MAX; + let mut quotes = [U256::MAX, U256::one()].into_iter(); + let primary_and_children = prepare_descendants( + &grant_params(), + Some(gl_call::Descendants::Pinned(vec![ + gl_call::AllocationNode::Internal(parent), + child, + ])), + |_| Ok(quotes.next().unwrap()), + ); + assert!(matches!( + primary_and_children, + Err(GrantValidationError::Budget) + )); + + let gl_call::AllocationNode::Internal(mut decided) = + internal_allocation(1, 1, gl_call::On::Decided, ROOT_PARENT) + else { + unreachable!() + }; + decided.budget = U256::MAX; + let mut enclosing = grant_params(); + enclosing.rotations.push(U256::zero()); + let decided_multiplier = prepare_descendants( + &enclosing, + Some(gl_call::Descendants::Pinned(vec![ + gl_call::AllocationNode::Internal(decided), + ])), + |_| Ok(U256::MAX / U256::from(2) + U256::one()), + ); + assert!(matches!( + decided_multiplier, + Err(GrantValidationError::Budget) + )); + + let mut external = external_allocation_node(U256::MAX); + let gl_call::AllocationNode::External(node) = &mut external else { + unreachable!() + }; + node.fee_params.gas_limit = U256::MAX; + node.fee_params.max_gas_price = U256::from(2); + let external_unit = prepare(Some(gl_call::Descendants::Pinned(vec![external]))); + assert!(matches!(external_unit, Err(GrantValidationError::External))); +} + fn errno(e: generated::types::Error) -> generated::types::Errno { e.downcast().expect("expected a plain errno, got a trap") } @@ -446,6 +943,19 @@ impl EmissionTestContext { } fn with_fees(memory_limit: u32, fee_total: u64, fees: crate::config::FeesConfig) -> Self { + Self::with_fees_and_balance(memory_limit, fee_total, fees, U256::MAX) + } + + fn with_balance(memory_limit: u32, fee_total: u64, balance: U256) -> Self { + Self::with_fees_and_balance(memory_limit, fee_total, emission_fees(), balance) + } + + fn with_fees_and_balance( + memory_limit: u32, + fee_total: u64, + fees: crate::config::FeesConfig, + balance: U256, + ) -> Self { let root = TestDir::new(); let runners_dir = root.join("runners"); let registry_dir = root.join("registry"); @@ -536,7 +1046,7 @@ impl EmissionTestContext { .unwrap(); supervisor .balances - .insert(calldata::Address::zero(), U256::MAX); + .insert(calldata::Address::zero(), balance); let limiter = rt::memlimiter::Limiter::with_limit(memory_limit); let permissions = base::Permissions { @@ -658,10 +1168,13 @@ impl EmissionTestContext { args: None, kwargs: None, }, - U256::zero(), - gl_call::On::Finalized, - use_balance, - use_balance.then(valid_params), + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance, + fee_params: use_balance.then(valid_params), + descendants: None, + }, ) .await } @@ -679,6 +1192,7 @@ impl EmissionTestContext { value: U256::zero(), salt_nonce: U256::zero(), use_balance, + descendants: None, }, ) .await @@ -1375,6 +1889,460 @@ async fn child_budget_overflow_is_internal_and_has_no_effect() { test.shutdown().await; } +#[tokio::test] +async fn balance_descendant_grant_is_emitted_and_reserved_once() { + let mut test = EmissionTestContext::new(u32::MAX, 100); + + test.wasi() + .gl_call_emit_internal_message( + calldata::Address::zero(), + abi::entry::MainCallData { + name: None, + args: None, + kwargs: None, + }, + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance: true, + fee_params: Some(valid_params()), + descendants: Some(gl_call::Descendants::Open(U256::from(3))), + }, + ) + .await + .unwrap(); + + let [domain::ExecutionEmission::InternalMessage { + message_fee, + subtree, + use_balance, + .. + }] = test.context.data.accumulator.emissions.as_slice() + else { + panic!("expected one internal message") + }; + assert!(*use_balance); + assert_eq!(*message_fee, U256::from(4)); + assert_eq!(subtree.len(), 224); + assert_eq!( + test.context.data.accumulator.messages_value_decremented, + U256::from(4) + ); + assert_eq!( + test.context + .data + .supervisor + .shared_data + .data_fees_limit + .consumed() + .await + .message_fee, + U256::zero() + ); + + test.shutdown().await; +} + +#[tokio::test] +async fn balance_deploy_descendant_grant_is_emitted_and_reserved_once() { + let mut test = EmissionTestContext::new(u32::MAX, 100); + + test.wasi() + .gl_call_emit_internal_deploy_message( + abi::entry::MainDeployData { + args: None, + kwargs: None, + }, + gl_call::On::Finalized, + Some(valid_params()), + EmitInternalDeployMessageArgs { + code: bytes::Bytes::new(), + value: U256::zero(), + salt_nonce: U256::zero(), + use_balance: true, + descendants: Some(gl_call::Descendants::Open(U256::from(3))), + }, + ) + .await + .unwrap(); + + let [domain::ExecutionEmission::InternalDeployMessage { + message_fee, + subtree, + use_balance, + .. + }] = test.context.data.accumulator.emissions.as_slice() + else { + panic!("expected one internal deploy message") + }; + assert!(*use_balance); + assert_eq!(*message_fee, U256::from(4)); + assert_eq!(subtree.len(), 224); + assert_eq!( + test.context.data.accumulator.messages_value_decremented, + U256::from(4) + ); + + test.shutdown().await; +} + +#[tokio::test] +async fn zero_declared_budget_balance_messages_are_rejected() { + let mut fees = emission_fees(); + fees.message_fee.delta_expr = "\\attrs = 0".to_owned(); + let mut test = EmissionTestContext::with_fees(u32::MAX, 100, fees); + + let error = test + .wasi() + .gl_call_emit_internal_message( + calldata::Address::zero(), + abi::entry::MainCallData { + name: None, + args: None, + kwargs: None, + }, + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance: true, + fee_params: Some(valid_params()), + descendants: None, + }, + ) + .await + .unwrap_err(); + let message = trap_message(error); + assert!( + message.contains("fee below_minimum"), + "unexpected error: {message}" + ); + + let error = test + .wasi() + .gl_call_emit_internal_deploy_message( + abi::entry::MainDeployData { + args: None, + kwargs: None, + }, + gl_call::On::Finalized, + Some(valid_params()), + EmitInternalDeployMessageArgs { + code: bytes::Bytes::new(), + value: U256::zero(), + salt_nonce: U256::zero(), + use_balance: true, + descendants: Some(gl_call::Descendants::Open(U256::zero())), + }, + ) + .await + .unwrap_err(); + let message = trap_message(error); + assert!( + message.contains("fee below_minimum"), + "unexpected error: {message}" + ); + + assert!(test.context.data.accumulator.emissions.is_empty()); + assert!(test + .context + .data + .accumulator + .messages_value_decremented + .is_zero()); + + test.shutdown().await; +} + +#[tokio::test] +async fn descendant_budget_is_included_in_the_balance_check() { + let mut test = EmissionTestContext::with_balance(u32::MAX, 100, U256::one()); + let memory_before = test.context.limiter.get_remaining_memory(); + + let error = test + .wasi() + .gl_call_emit_internal_message( + calldata::Address::zero(), + abi::entry::MainCallData { + name: None, + args: None, + kwargs: None, + }, + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance: true, + fee_params: Some(valid_params()), + descendants: Some(gl_call::Descendants::Open(U256::from(3))), + }, + ) + .await + .unwrap_err(); + + assert_eq!(errno(error), generated::types::Errno::InsufficientBalance); + assert!(test.context.data.accumulator.emissions.is_empty()); + assert_eq!(test.context.limiter.get_remaining_memory(), memory_before); + assert_eq!(test.context.limiter.get_new_permanent_allocations(), 0); + assert_eq!( + test.context.data.accumulator.messages_value_decremented, + U256::zero() + ); + + test.shutdown().await; +} + +#[tokio::test] +async fn descendant_grants_are_forbidden_without_permission_or_in_nondet_mode() { + for remove_permission in [true, false] { + let mut test = EmissionTestContext::new(u32::MAX, 100); + if remove_permission { + test.context + .data + .conf + .permissions + .can_use_balance_for_message_fees = false; + } else { + test.context.data.conf.permissions.deterministic = false; + } + + let error = test + .wasi() + .gl_call_emit_internal_message( + calldata::Address::zero(), + abi::entry::MainCallData { + name: None, + args: None, + kwargs: None, + }, + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance: true, + fee_params: Some(valid_params()), + descendants: Some(gl_call::Descendants::Open(U256::one())), + }, + ) + .await + .unwrap_err(); + + assert_eq!(errno(error), generated::types::Errno::Forbidden); + assert!(test.context.data.accumulator.emissions.is_empty()); + assert_eq!( + test.context.data.accumulator.messages_value_decremented, + U256::zero() + ); + test.shutdown().await; + } +} + +#[tokio::test] +async fn repeated_descendant_grants_drain_the_contract_balance() { + let mut test = EmissionTestContext::with_balance(u32::MAX, 100, U256::from(8)); + + for _ in 0..2 { + test.wasi() + .gl_call_emit_internal_message( + calldata::Address::zero(), + abi::entry::MainCallData { + name: None, + args: None, + kwargs: None, + }, + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance: true, + fee_params: Some(valid_params()), + descendants: Some(gl_call::Descendants::Open(U256::from(3))), + }, + ) + .await + .unwrap(); + } + + let error = test + .wasi() + .gl_call_emit_internal_message( + calldata::Address::zero(), + abi::entry::MainCallData { + name: None, + args: None, + kwargs: None, + }, + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance: true, + fee_params: Some(valid_params()), + descendants: Some(gl_call::Descendants::Open(U256::from(3))), + }, + ) + .await + .unwrap_err(); + + assert_eq!(errno(error), generated::types::Errno::InsufficientBalance); + assert_eq!(test.context.data.accumulator.emissions.len(), 2); + assert_eq!( + test.context.data.accumulator.messages_value_decremented, + U256::from(8) + ); + + test.shutdown().await; +} + +#[tokio::test] +async fn allocation_funding_accepts_absent_descendants_and_rejects_explicit_descendants() { + let mut test = EmissionTestContext::new(u32::MAX, 100); + + test.wasi() + .gl_call_emit_internal_message( + calldata::Address::zero(), + abi::entry::MainCallData { + name: None, + args: None, + kwargs: None, + }, + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance: false, + fee_params: None, + descendants: None, + }, + ) + .await + .unwrap(); + + for descendants in [ + gl_call::Descendants::Open(U256::zero()), + gl_call::Descendants::Pinned(vec![]), + ] { + let error = test + .wasi() + .gl_call_emit_internal_message( + calldata::Address::zero(), + abi::entry::MainCallData { + name: None, + args: None, + kwargs: None, + }, + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance: false, + fee_params: None, + descendants: Some(descendants), + }, + ) + .await + .unwrap_err(); + assert_eq!(errno(error), generated::types::Errno::Inval); + } + + assert_eq!(test.context.data.accumulator.emissions.len(), 1); + test.shutdown().await; +} + +#[tokio::test] +async fn rejected_descendant_grant_has_no_emission_reservation_or_fee_effect() { + let mut test = EmissionTestContext::new(u32::MAX, 100); + let memory_before = test.context.limiter.get_remaining_memory(); + let node = internal_allocation(1, 1, gl_call::On::Finalized, ROOT_PARENT); + + let error = test + .wasi() + .gl_call_emit_internal_message( + calldata::Address::zero(), + abi::entry::MainCallData { + name: None, + args: None, + kwargs: None, + }, + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance: true, + fee_params: Some(valid_params()), + descendants: Some(gl_call::Descendants::Pinned(vec![node.clone(), node])), + }, + ) + .await + .unwrap_err(); + + assert!( + trap_message(error).contains("fee descendant_grant tree"), + "unexpected grant error" + ); + assert!(test.context.data.accumulator.emissions.is_empty()); + assert_eq!(test.context.limiter.get_remaining_memory(), memory_before); + assert_eq!(test.context.limiter.get_new_permanent_allocations(), 0); + assert_eq!( + test.context.data.accumulator.messages_value_decremented, + U256::zero() + ); + let consumed = test + .context + .data + .supervisor + .shared_data + .data_fees_limit + .consumed() + .await; + assert_eq!(consumed.message_fee, U256::zero()); + assert_eq!(consumed.message_receipt, U256::zero()); + + test.shutdown().await; +} + +#[tokio::test] +async fn descendant_budget_overflow_has_no_emission_reservation_or_fee_effect() { + let mut test = EmissionTestContext::new(u32::MAX, 100); + let memory_before = test.context.limiter.get_remaining_memory(); + + let error = test + .wasi() + .gl_call_emit_internal_message( + calldata::Address::zero(), + abi::entry::MainCallData { + name: None, + args: None, + kwargs: None, + }, + EmitInternalMessageArgs { + value: U256::zero(), + on: gl_call::On::Finalized, + use_balance: true, + fee_params: Some(valid_params()), + descendants: Some(gl_call::Descendants::Open(U256::MAX)), + }, + ) + .await + .unwrap_err(); + + assert!( + trap_message(error).contains("fee descendant_grant budget"), + "unexpected grant error" + ); + assert!(test.context.data.accumulator.emissions.is_empty()); + assert_eq!(test.context.limiter.get_remaining_memory(), memory_before); + assert_eq!(test.context.limiter.get_new_permanent_allocations(), 0); + assert_eq!( + test.context.data.accumulator.messages_value_decremented, + U256::zero() + ); + let consumed = test + .context + .data + .supervisor + .shared_data + .data_fees_limit + .consumed() + .await; + assert_eq!(consumed.message_fee, U256::zero()); + assert_eq!(consumed.message_receipt, U256::zero()); + + test.shutdown().await; +} + #[tokio::test] async fn event_rejected_by_memory_is_not_appended_or_charged() { let mut test = EmissionTestContext::new(0, 1); @@ -1510,6 +2478,7 @@ fn flat_argument_request(deploy: bool) -> (Vec, u32) { salt_nonce: U256::zero(), use_balance: true, fee_params: Some(params), + descendants: None, } } else { gl_call::Message::EmitInternalMessage { @@ -1523,6 +2492,7 @@ fn flat_argument_request(deploy: bool) -> (Vec, u32) { on: gl_call::On::Finalized, use_balance: true, fee_params: Some(params), + descendants: None, } }; (calldata::encode_obj(&request), memory) @@ -1663,6 +2633,7 @@ async fn gl_call_internal_message_retains_calldata_args_as_validated_wire_bytes( on: gl_call::On::Finalized, use_balance: false, fee_params: None, + descendants: None, }); gl_call_wire(&mut test, &request).await.unwrap(); @@ -1962,6 +2933,17 @@ fn zero_price_caps_are_inval() { } } +#[test] +fn mixed_zero_time_units_are_inval_without_descendants() { + for (leader, validator) in [(U256::zero(), U256::one()), (U256::one(), U256::zero())] { + let mut params = valid_params(); + params.leader_time_units_allocation = leader; + params.validator_time_units_allocation = validator; + let error = validate_balance_fee(true, true, Some(params)).unwrap_err(); + assert_eq!(errno(error), generated::types::Errno::Inval); + } +} + #[test] fn huge_magnitude_params_are_inval() { // Security-review N1 repro: passes the emptiness/zero checks, but the @@ -1969,7 +2951,7 @@ fn huge_magnitude_params_are_inval() { // evaluator's result to U256::MAX. let p = abi::fees::InternalMessageParams { leader_time_units_allocation: U256::one() << 250, - validator_time_units_allocation: U256::zero(), + validator_time_units_allocation: U256::one(), execution_budget_per_round: U256::zero(), rotations: vec![U256::zero()], max_price_gen_per_time_unit: U256::one() << 250, @@ -2454,6 +3436,9 @@ fn proposable_generated_trie_codes_are_accepted() { public_abi::VmError::out_of().receipt().nondet_output(), public_abi::VmError::out_of().message_fee().total().val(), public_abi::VmError::fee().below_minimum(), + public_abi::VmError::fee().descendant_grant().budget(), + public_abi::VmError::fee().descendant_grant().tree(), + public_abi::VmError::fee().descendant_grant().external(), public_abi::VmError::evm().reverted(), public_abi::VmError::invalid_contract().val(), public_abi::VmError::invalid_contract().wasm().linking(), diff --git a/executor/tests/message_fee_time_units.rs b/executor/tests/message_fee_time_units.rs index 0482f467..7ea457d4 100644 --- a/executor/tests/message_fee_time_units.rs +++ b/executor/tests/message_fee_time_units.rs @@ -144,3 +144,19 @@ fn no_appeals_reserve_no_appeal_profit() { U256::from(8) ); } + +#[test] +fn descendant_quote_skips_unavailable_pinned_budget_floor() { + let mut gas_data = gas_data(1, 100, 1, 100); + gas_data.insert("messageBudgetFloor".to_owned(), "2".to_owned()); + let fees = DataLimit::new(bucket_totals(), default_fees(), gas_data).unwrap(); + let params = fee_params(2, 1); + + assert!(fees.calculate_message_fee_internal(¶ms).is_err()); + assert_eq!( + fees.calculate_descendant_message_fee_internal(¶ms) + .unwrap() + .reported_fee(), + U256::from(8) + ); +} diff --git a/manifest.json b/manifest.json index 17f0c53f..c6f506a6 100644 --- a/manifest.json +++ b/manifest.json @@ -1,4 +1,4 @@ { - "executor-version": "v0.3.0-rc9", + "executor-version": "v0.3.0-rc10", "available-after": "2024-09-01T00:00:00Z" } diff --git a/runners/genlayer-py-std/src/genlayer/__init__.py b/runners/genlayer-py-std/src/genlayer/__init__.py index 2d14da1b..419c08f3 100644 --- a/runners/genlayer-py-std/src/genlayer/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/__init__.py @@ -52,6 +52,7 @@ 'contract', 'chain', 'message', + 'message_allocation', 'vm', 'evm', 'nondet', @@ -152,6 +153,7 @@ evm, gvm32, message, + message_allocation, nondet, storage, types, @@ -162,6 +164,7 @@ _lazy_modules = { 'contract': 'genlayer.contract', 'message': 'genlayer.message', + 'message_allocation': 'genlayer.message_allocation', 'vm': 'genlayer.vm', 'evm': 'genlayer.evm', 'nondet': 'genlayer.nondet', diff --git a/runners/genlayer-py-std/src/genlayer/calldata/__init__.py b/runners/genlayer-py-std/src/genlayer/calldata/__init__.py index 08d6b7ca..95fefb5c 100644 --- a/runners/genlayer-py-std/src/genlayer/calldata/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/calldata/__init__.py @@ -149,6 +149,8 @@ def __hash__(self) -> int: def encode_default_parameter(b, /): + if isinstance(b, CalldataEncodable): + return b if not dataclasses.is_dataclass(b): return b if isinstance(b, type): diff --git a/runners/genlayer-py-std/src/genlayer/chain.py b/runners/genlayer-py-std/src/genlayer/chain.py index e45e7d3c..d6a18d99 100644 --- a/runners/genlayer-py-std/src/genlayer/chain.py +++ b/runners/genlayer-py-std/src/genlayer/chain.py @@ -1,8 +1,21 @@ -__all__ = ('ON', 'IAccount', 'Account', 'Event', 'InternalMessageParams', 'id') +__all__ = ( + 'ON', + 'IAccount', + 'Account', + 'Event', + 'ExternalMessageParams', + 'InternalMessageParams', + 'id', +) import dataclasses import typing +import genlayer + +if typing.TYPE_CHECKING: + import genlayer.message_allocation + import genlayer._internal.on_chain.gl_call as gl_call import genlayer.calldata as calldata from genlayer import IS_IN_VM @@ -17,8 +30,8 @@ class InternalMessageParams(calldata.DataclassMixin): """ Fee parameters for a balance-funded internal message (``use_balance``). GenVM - meters the fee from these params (against the emitting contract's balance) and - that metered amount becomes the child transaction's ``declaredBudget``. + meters the primary fee from these params against the emitting contract's balance. + The child transaction's ``declaredBudget`` also includes its descendant grant. Field names and layout mirror the executor's calldata encoding exactly. @@ -40,6 +53,13 @@ class InternalMessageParams(calldata.DataclassMixin): receipt_fee_max_gas_price: u256 +@typing.final +@dataclasses.dataclass(frozen=True) +class ExternalMessageParams(calldata.DataclassMixin): + gas_limit: u256 + max_gas_price: u256 + + @typing.runtime_checkable class IAccount(typing.Protocol): """ @@ -61,11 +81,18 @@ def balance(self) -> u256: """ ... - def emit_transfer(self, value: u256, *, on: ON = 'finalized') -> None: + def emit_transfer( + self, + value: u256, + use_balance: 'genlayer.message_allocation.UseBalanceParams | None' = None, + *, + on: ON = 'finalized', + ) -> None: """ Emit a transfer message to this account's address. :param value: amount to transfer + :param use_balance: Balance funding parameters, or None for sender funding :param on: transaction stage at which the transfer is applied """ ... @@ -105,16 +132,23 @@ def balance(self) -> u256: return get_at(self.address).balance - def emit_transfer(self, value: u256, *, on: ON = 'finalized') -> None: + def emit_transfer( + self, + value: u256, + use_balance: 'genlayer.message_allocation.UseBalanceParams | None' = None, + *, + on: ON = 'finalized', + ) -> None: """ Emit a transfer message to this account's address. :param value: amount to transfer + :param use_balance: Balance funding parameters, or None for sender funding :param on: transaction stage at which the transfer is applied """ from genlayer.contract import get_at - get_at(self.address).emit_transfer(value, on=on) + get_at(self.address).emit_transfer(value, use_balance, on=on) import inspect # noqa: E402 diff --git a/runners/genlayer-py-std/src/genlayer/contract/__init__.py b/runners/genlayer-py-std/src/genlayer/contract/__init__.py index ade4cdc0..0a6674de 100644 --- a/runners/genlayer-py-std/src/genlayer/contract/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/contract/__init__.py @@ -17,6 +17,7 @@ 'GenVMContractDeclaration', 'StorageView', 'ON', + 'UseBalanceParams', ) import collections.abc @@ -25,7 +26,8 @@ import genlayer.calldata as calldata from genlayer import IS_IN_VM -from genlayer.chain import IAccount, InternalMessageParams +from genlayer.chain import IAccount +from genlayer.message_allocation import UseBalanceParams, _flatten_allocations from genlayer.types import Address, Lazy, u256 if typing.TYPE_CHECKING or IS_IN_VM: @@ -37,6 +39,36 @@ """When the transaction message should be applied: ``'decided'`` or ``'finalized'``""" +def _balance_fields( + use_balance: UseBalanceParams | None, +) -> dict[str, calldata.Encodable]: + if use_balance is None: + return {} + if not isinstance(use_balance, UseBalanceParams): + raise TypeError('use_balance must be UseBalanceParams or None') + descendants = use_balance.descendants + if isinstance(descendants, bool): + raise TypeError('descendants must not be bool') + if isinstance(descendants, (str, bytes, bytearray)): + raise TypeError('descendants must not be str, bytes, or bytearray') + closed = ( + descendants is None + or (isinstance(descendants, int) and descendants == 0) + or (isinstance(descendants, collections.abc.Sequence) and not descendants) + ) + fields: dict[str, calldata.Encodable] = { + 'use_balance': True, + 'fee_params': use_balance.fee_params, + } + if not closed: + fields['descendants'] = ( + _flatten_allocations(descendants) + if isinstance(descendants, collections.abc.Sequence) + else descendants + ) + return fields + + def _make_calldata_obj(method, args, kwargs) -> calldata.Encodable: ret = {} if method is not None: @@ -96,7 +128,13 @@ def lazy(self, *args, **kwargs) -> Lazy[calldata.Decoded | VMError]: class _ContractAtEmitMethod: - __slots__ = ('_addr', '_fee_params', '_name', '_on', '_use_balance', '_value') + __slots__ = ( + '_addr', + '_name', + '_on', + '_use_balance', + '_value', + ) def __init__( self, @@ -104,15 +142,13 @@ def __init__( addr: Address, value: u256, on: str, - use_balance: bool = False, - fee_params: InternalMessageParams | None = None, + use_balance: UseBalanceParams | None = None, ): self._addr = addr self._name = name self._value = value self._on = on self._use_balance = use_balance - self._fee_params = fee_params def __call__(self, *args, **kwargs) -> None: message: dict[str, calldata.Encodable] = { @@ -121,10 +157,7 @@ def __call__(self, *args, **kwargs) -> None: 'value': self._value, 'on': self._on, } - if self._use_balance: - message['use_balance'] = True - if self._fee_params is not None: - message['fee_params'] = self._fee_params + message.update(_balance_fields(self._use_balance)) wasi.gl_call(calldata.encode({'EmitInternalMessage': message})) @@ -182,22 +215,19 @@ def view( def emit( self, + use_balance: UseBalanceParams | None = None, *, value: u256 = 0, on: ON = 'finalized', - use_balance: bool = False, - fee_params: InternalMessageParams | None = None, ) -> TSend: """ Get a namespace for emitting write transactions. :param value: Amount of native tokens to transfer with the transaction :param on: When the transaction message should be emitted to consensus - :param use_balance: Fund the message fee from this contract's balance instead - of the sender's prefunded pool. Requires the - ``can_use_balance_for_message_fees`` permission and ``fee_params``. - :param fee_params: Fee parameters GenVM meters the balance-funded fee from; - required when ``use_balance`` is set, ignored otherwise + :param use_balance: Balance funding parameters, or None to use the sender's + prefunded pool. Balance funding requires + ``can_use_balance_for_message_fees`` permission :returns: Object providing access to write methods .. warning:: @@ -209,10 +239,9 @@ def emit( def emit_transfer( self, value: u256, + use_balance: UseBalanceParams | None = None, *, on: ON = 'finalized', - use_balance: bool = False, - fee_params: InternalMessageParams | None = None, ) -> None: """ Emit a simple value transfer without calling any method. Receiver may catch it with @@ -221,7 +250,6 @@ def emit_transfer( :param value: Amount of native tokens to transfer :param on: When transaction message should be emitted to consensus :param use_balance: Fund the message fee from this contract's balance; see :py:meth:`emit` - :param fee_params: Fee parameters for the balance-funded fee; required when ``use_balance`` is set :raises ValueError: If value is zero """ @@ -304,27 +332,29 @@ def view( def emit( self, + use_balance: UseBalanceParams | None = None, *, value: u256 = 0, on: ON = 'finalized', - use_balance: bool = False, - fee_params: InternalMessageParams | None = None, ) -> ErasedMethods: return _ContractAtGetter( - _ContractAtEmitMethod, self._address, value, on, use_balance, fee_params + _ContractAtEmitMethod, + self._address, + value, + on, + use_balance, ) def emit_transfer( self, value: u256, + use_balance: UseBalanceParams | None = None, *, on: ON = 'finalized', - use_balance: bool = False, - fee_params: InternalMessageParams | None = None, ) -> None: if value <= 0: raise ValueError('value must be greater than 0 for emit_transfer') - _ContractAtEmitMethod(None, self._address, value, on, use_balance, fee_params)() + _ContractAtEmitMethod(None, self._address, value, on, use_balance)() @property def balance(self) -> u256: @@ -454,6 +484,7 @@ def interface[TView, TWrite]( @typing.overload def deploy( + use_balance: UseBalanceParams | None = None, *, code: bytes, args: collections.abc.Sequence[calldata.Encodable] = [], @@ -461,13 +492,12 @@ def deploy( salt_nonce: typing.Literal[0] = 0, value: u256 = 0, on: ON = 'finalized', - use_balance: bool = False, - fee_params: InternalMessageParams | None = None, ) -> None: ... @typing.overload def deploy( + use_balance: UseBalanceParams | None = None, *, code: bytes, args: collections.abc.Sequence[calldata.Encodable] = [], @@ -475,12 +505,11 @@ def deploy( salt_nonce: u256, value: u256 = 0, on: ON = 'finalized', - use_balance: bool = False, - fee_params: InternalMessageParams | None = None, -) -> Address: ... +) -> Address | None: ... def deploy( + use_balance: UseBalanceParams | None = None, *, code: bytes, args: collections.abc.Sequence[calldata.Encodable] = [], @@ -488,8 +517,6 @@ def deploy( salt_nonce: u256 | typing.Literal[0] = 0, value: u256 = 0, on: ON = 'finalized', - use_balance: bool = False, - fee_params: InternalMessageParams | None = None, ) -> Address | None: """ Deploy a new GenVM contract to the blockchain. @@ -505,7 +532,6 @@ def deploy( :param value: Amount of native tokens to send to the contract during deployment :param on: When to execute the deployment ('decided' or 'finalized') :param use_balance: Fund the deploy message fee from this contract's balance; see :py:meth:`Proxy.emit` - :param fee_params: Fee parameters for the balance-funded fee; required when ``use_balance`` is set :returns: Contract address if salt_nonce != 0, None otherwise Example: @@ -543,10 +569,7 @@ def deploy( 'on': on, 'salt_nonce': salt_nonce, } - if use_balance: - message['use_balance'] = True - if fee_params is not None: - message['fee_params'] = fee_params + message.update(_balance_fields(use_balance)) wasi.gl_call(calldata.encode({'EmitInternalDeployMessage': message})) if salt_nonce == 0: @@ -617,13 +640,19 @@ def address(self) -> Address: return message.contract_address - def emit_transfer(self, value: u256, *, on: ON = 'finalized') -> None: + def emit_transfer( + self, + value: u256, + use_balance: UseBalanceParams | None = None, + *, + on: ON = 'finalized', + ) -> None: import warnings warnings.warn('Emitting transfer to self without data makes little sense') from genlayer.contract import get_at - get_at(self.address).emit_transfer(value, on=on) + get_at(self.address).emit_transfer(value, use_balance, on=on) def __handle_undefined_method__( self, method_name: str, args: list[typing.Any], kwargs: dict[str, typing.Any] diff --git a/runners/genlayer-py-std/src/genlayer/message_allocation.py b/runners/genlayer-py-std/src/genlayer/message_allocation.py new file mode 100644 index 00000000..40ad4133 --- /dev/null +++ b/runners/genlayer-py-std/src/genlayer/message_allocation.py @@ -0,0 +1,139 @@ +__all__ = ( + 'ANY_METHOD', + 'Descendants', + 'ExternalAllocation', + 'InternalAllocation', + 'UseBalanceParams', +) + +import collections.abc +import dataclasses +import typing + +import genlayer.calldata as calldata +from genlayer.chain import ON, ExternalMessageParams, InternalMessageParams +from genlayer.types import Address, Keccak256, u256 + +ANY_METHOD: typing.Final = Keccak256(b'').digest() +""" + Call key matching any method +""" + +_ROOT: typing.Final[u256] = (1 << 256) - 1 + + +def _resolve_call_key(call_key: str | bytes | None) -> bytes: + if call_key is None: + return ANY_METHOD + if isinstance(call_key, bytes): + if len(call_key) != 32: + raise ValueError('call_key bytes must be exactly 32 bytes') + return call_key + if not isinstance(call_key, str): + raise TypeError('call_key must be str, bytes, or None') + + name = call_key.encode() + if len(name) < 32: + return name.ljust(32, b'\0') + result = bytearray(Keccak256(name).digest()) + result[-1] |= 1 + return bytes(result) + + +def _resolve_external_call_key(call_key: bytes | None) -> bytes: + if call_key is not None and not isinstance(call_key, bytes): + raise TypeError('external call_key must be bytes or None') + if isinstance(call_key, bytes): + if len(call_key) == 4: + return call_key + bytes(28) + if len(call_key) != 32: + raise ValueError('external call_key bytes must be 4 or 32 bytes') + return _resolve_call_key(call_key) + + +@typing.final +@dataclasses.dataclass(frozen=True) +class InternalAllocation(calldata.CalldataEncodable): + """ + Allocation for an internal descendant message + + ``call_key`` is a method name, a raw 32-byte key, or None for any method + Use ``bytes(32)`` for deploys and transfers + """ + + recipient: Address + call_key: str | bytes | None + fee_params: InternalMessageParams + budget: u256 + on: ON = 'finalized' + children: list['InternalAllocation'] = dataclasses.field(default_factory=list) + + def __to_calldata__(self): + return { + 'recipient': self.recipient, + 'call_key': _resolve_call_key(self.call_key), + 'budget': self.budget, + 'fee_params': self.fee_params, + 'on': self.on, + } + + +@typing.final +@dataclasses.dataclass(frozen=True) +class ExternalAllocation(calldata.CalldataEncodable): + """ + Allocation for an external descendant message + + ``call_key`` is a 4-byte selector, a raw 32-byte key, or None for any method + Use ``bytes(32)`` for empty calldata + """ + + recipient: Address + call_key: bytes | None + fee_params: ExternalMessageParams + budget: u256 + + def __to_calldata__(self): + return { + 'recipient': self.recipient, + 'call_key': _resolve_external_call_key(self.call_key), + 'budget': self.budget, + 'fee_params': self.fee_params, + } + + +type Descendants = ( + None | u256 | collections.abc.Sequence[InternalAllocation | ExternalAllocation] +) + + +@typing.final +@dataclasses.dataclass(frozen=True) +class UseBalanceParams: + fee_params: InternalMessageParams + descendants: Descendants = None + + +def _flatten_allocations( + roots: collections.abc.Iterable[InternalAllocation | ExternalAllocation], +): + result = [] + pending = [(iter(roots), _ROOT)] + while pending: + nodes, parent_index = pending[-1] + try: + node = next(nodes) + except StopIteration: + pending.pop() + continue + if len(result) >= 1024: + raise ValueError('descendants must contain at most 1024 allocations') + if not isinstance(node, (InternalAllocation, ExternalAllocation)): + raise TypeError('descendants must contain allocation objects') + index = len(result) + fields = node.__to_calldata__() + fields['parent_index'] = parent_index + result.append(fields) + if isinstance(node, InternalAllocation): + pending.append((iter(node.children), index)) + return result diff --git a/runners/genlayer-py-std/src/genlayer/storage/core.py b/runners/genlayer-py-std/src/genlayer/storage/core.py index 85dc66d5..95190bbe 100644 --- a/runners/genlayer-py-std/src/genlayer/storage/core.py +++ b/runners/genlayer-py-std/src/genlayer/storage/core.py @@ -522,6 +522,30 @@ def copy(self, frm: Slot, frm_off: int, to: Slot, to_off: int) -> int: return VLATypeDesc.SIZE +@typing.final +class ZeroManager(Manager): + """ + Read-only singleton storage source that returns zero-filled bytes. + """ + + _instance: typing.ClassVar['ZeroManager | None'] = None + __slots__ = () + + def __new__(cls): + if cls._instance is None: + cls._instance = super().__new__(cls) + return cls._instance + + def get_store_slot(self, slot_id: bytes | u256, /) -> Slot: + return Slot(slot_id_to_bytes(slot_id), self) + + def do_read(self, slot_id: bytes, off: int, len: int, /) -> bytes: + return bytes(len) + + def do_write(self, slot_id: bytes, off: int, what: collections.abc.Buffer, /): + raise TypeError('zero storage is read-only') + + class InmemManager(Manager): """ In-memory storage backend, useful for testing. diff --git a/runners/genlayer-py-std/src/genlayer/storage/dyn_array.py b/runners/genlayer-py-std/src/genlayer/storage/dyn_array.py index 24f5538c..52a9e90e 100644 --- a/runners/genlayer-py-std/src/genlayer/storage/dyn_array.py +++ b/runners/genlayer-py-std/src/genlayer/storage/dyn_array.py @@ -44,11 +44,11 @@ def _map_index(self, idx: int) -> int: return idx @typing.overload - def __getitem__(self, idx: int) -> T: ... + def __getitem__(self, idx: typing.SupportsIndex) -> T: ... @typing.overload def __getitem__(self, idx: slice) -> list[T]: ... - def __getitem__(self, idx: int | slice) -> T | list[T]: + def __getitem__(self, idx: typing.SupportsIndex | slice) -> T | list[T]: """ Get element by index or sublist by slice. @@ -56,8 +56,8 @@ def __getitem__(self, idx: int | slice) -> T | list[T]: :returns: single element for int index, list of elements for slice :raises IndexError: when integer index is out of range """ - if isinstance(idx, int): - idx = self._map_index(idx) + if not isinstance(idx, slice): + idx = self._map_index(operator.index(idx)) items_at = self._storage_slot.indirect(self._off) return self._item_desc.get(items_at, idx * self._item_desc.size) else: @@ -83,24 +83,32 @@ def __setitem__( :param idx: integer index or slice :param val: value or sequence of values to assign :raises IndexError: when integer index is out of range + :raises ValueError: when an extended slice (step other than 1) and the + sequence differ in length, as for :class:`list` If assigning an element or one of several slice elements fails, earlier writes made by this operation remain visible. A failed extending slice assignment changes the length only after all new elements are written. """ if not isinstance(idx, slice): - idx = self._map_index(idx.__index__()) + idx = self._map_index(operator.index(idx)) items_at = self._storage_slot.indirect(self._off) self._item_desc.set(items_at, idx * self._item_desc.size, val) return else: + signed_step = 1 if idx.step is None else operator.index(idx.step) + idx = slice(idx.start, idx.stop, signed_step) start, stop, step = self._slice_to_idx(idx) # materialized: the algorithm below needs `len` and reversal new_val = list(typing.cast(collections.abc.Iterable[T], val)) left_in_new = len(new_val) - if isinstance(idx.step, int) and idx.step < 0: + if signed_step < 0: new_val.reverse() - left_in_range = (stop - start) // step + left_in_range = len(range(start, stop, step)) + if signed_step != 1 and left_in_new != left_in_range: + raise ValueError( + f'attempt to assign sequence of size {left_in_new} to extended slice of size {left_in_range}' + ) new_it = iter(new_val) # just reassign existing values @@ -141,11 +149,11 @@ def _slice_to_idx(self, s: slice) -> tuple[int, int, int]: return start, stop, step @typing.overload - def __delitem__(self, idx: int) -> None: ... + def __delitem__(self, idx: typing.SupportsIndex) -> None: ... @typing.overload def __delitem__(self, idx: slice) -> None: ... - def __delitem__(self, idx: int | slice) -> None: + def __delitem__(self, idx: typing.SupportsIndex | slice) -> None: """ Delete element by index or range by slice. @@ -155,8 +163,8 @@ def __delitem__(self, idx: int | slice) -> None: Elements are shifted before the length is reduced. If shifting fails, the original length and any shifts already completed remain visible. """ - if isinstance(idx, int): - start = self._map_index(idx) + if not isinstance(idx, slice): + start = self._map_index(operator.index(idx)) stop = start + 1 step = 1 else: @@ -178,12 +186,20 @@ def __delitem__(self, idx: int | slice) -> None: def assign(self, arr: typing.Sequence[T], /) -> typing.Self: """ Same as ``self[:] = arr`` but more efficient + Assigning from a view of the same array is a no-op .. admonition:: Exception safety :class: note On error list becomes empty """ + if ( + isinstance(arr, DynArray) + and arr._storage_slot == self._storage_slot + and arr._off == self._off + and arr._item_desc == self._item_desc + ): + return self _u32_desc.set(self._storage_slot, self._off, 0) for idx in range(len(arr)): items_at = self._storage_slot.indirect(self._off) @@ -255,10 +271,11 @@ def pop(self, index: typing.SupportsIndex = -1, /) -> T: :param index: element to remove (default last) :raises IndexError: when the array is empty or index is out of range - Storage-backed compound values are returned as views, not detached - Python objects. Removing a non-last element shifts another element into - the returned view's location; reusing the removed last slot can likewise - change a previously returned view. + .. warning:: + Storage-backed compound values are returned as live views. When removing + a non-last element, the returned view already refers to the shifted + element when ``pop()`` returns. Reusing the removed last slot can also + change a previously returned view. """ index = self._map_index(operator.index(index)) ret = self[index] diff --git a/runners/genlayer-py-std/src/genlayer/storage/tree_map.py b/runners/genlayer-py-std/src/genlayer/storage/tree_map.py index c619a295..34cc566d 100644 --- a/runners/genlayer-py-std/src/genlayer/storage/tree_map.py +++ b/runners/genlayer-py-std/src/genlayer/storage/tree_map.py @@ -6,10 +6,22 @@ from genlayer.types import i8, u32 +from ._internal.desc_record import RecordExtraFields from ._internal.generate import allow +from .core import Slot, ZeroManager, actions_apply_copy from .dyn_array import DynArray _NO_OBJ = object() +_active_suppliers: set[tuple[Slot, int]] = set() + + +def _record(view: object) -> RecordExtraFields: + return typing.cast(RecordExtraFields, view) + + +def _location(view: object) -> tuple[Slot, int]: + rec = _record(view) + return rec._storage_slot, rec._off @allow @@ -24,6 +36,16 @@ def __init__(self, k: K, v: V): self.key = k if v is not _NO_OBJ: self.value = v + else: + rec = _record(self) + field = rec.__type_desc__.layout.fields['value'] + actions_apply_copy( + field.desc.copy_actions, + rec._storage_slot, + rec._off + field.offset, + ZeroManager().get_store_slot(0), + 0, + ) self.left = 0 self.right = 0 self.balance = 0 @@ -52,13 +74,20 @@ class TreeMap[K: Comparable, V](collections.abc.MutableMapping[K, V]): _slots: DynArray[_Node[K, V]] _free_slots: DynArray[u32] + def _check_mutation(self): + if _location(self) in _active_suppliers: + raise RuntimeError('cannot mutate TreeMap during its supplier callback') + def clear(self): """ Remove all entries from the map. + :raises RuntimeError: if called during this map's supplier callback + The root is cleared before the backing arrays. If a storage write fails, the map may already appear empty while unreachable backing data remains. """ + self._check_mutation() self._root = 0 self._slots.clear() self._free_slots.clear() @@ -181,10 +210,12 @@ def __delitem__(self, k: K): :param k: key to remove :raises KeyError: when key is not found + :raises RuntimeError: if called during this map's supplier callback Key comparisons finish before mutation starts. A later storage error can leave the tree only partially updated; storage errors must not be caught. """ + self._check_mutation() seq, is_less = self._find_seq(k) # not found if seq[-1] == 0: @@ -319,12 +350,15 @@ def __setitem__(self, k: K, v: V): :param k: key :param v: value to associate with the key + :raises RuntimeError: if called during this map's supplier callback Overwriting an entry has the value encoder's exception safety. During an insertion, an encoding or storage error can leave an allocated node linked and partially initialized; such errors must not be caught. """ + self._check_mutation() + def setter(node: _Node[K, V]): node.value = v @@ -337,6 +371,7 @@ def setter(node: _Node[K, V]): def compute_if_absent(self, k: K, supplier: typing.Callable[[], V], /) -> V: """ :returns: Value associated with `k` if it is present, otherwise get's new value from the supplier, stores it at `k` and returns + :raises RuntimeError: if the supplier attempts to mutate this map through its mapping methods The supplier is called before storage is mutated. If encoding or storing the supplied value fails, insertion can remain partially applied. @@ -346,10 +381,18 @@ def compute_if_absent(self, k: K, supplier: typing.Callable[[], V], /) -> V: def existing(node: _Node[K, V]): res.append(node.value) + def supply(): + key = _location(self) + _active_suppliers.add(key) + try: + return supplier() + finally: + _active_suppliers.remove(key) + ret = self._get_set( k, existing, - supplier, + supply, ) return res[0] if res else ret @@ -359,6 +402,7 @@ def get_or_insert_default(self, k: K, /) -> V: :param k: key to look up or insert :returns: value associated with the key + :raises RuntimeError: if insertion is attempted during this map's supplier callback If insertion fails during a storage write, it can remain partially applied. """ @@ -380,6 +424,7 @@ def _get_set( slot = self._slots[seq[-1] - 1] exists(slot) return slot.value + self._check_mutation() # patch root if len(seq) == 1: value = does_not_exist() @@ -484,13 +529,21 @@ def get(self, k: K, /, default=None): def assign(self, arr: typing.Mapping[K, V], /) -> typing.Self: """ Clear the map and populate it from the given mapping. + Assigning from a view of the same map is a no-op. :param arr: mapping to copy entries from :returns: self + :raises RuntimeError: if replacement is attempted during this map's supplier callback The old map is cleared first. If iteration or insertion fails, entries inserted before the error remain visible. """ + if ( + isinstance(arr, TreeMap) + and _location(arr) == _location(self) + and _record(arr).__type_desc__ == _record(self).__type_desc__ + ): + return self self.clear() for k, v in arr.items(): self[k] = v 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 41d7cf49..96a4cb31 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/public_abi.py +++ b/runners/genlayer-py-std/src/genlayer/vm/public_abi.py @@ -224,6 +224,17 @@ def internal() -> 'VmError': def external() -> 'VmError': return VmError('fee no_matching_allocation # external') +class _VmErrorFeeDescendantGrant: + @staticmethod + def budget() -> 'VmError': + return VmError('fee descendant_grant budget') + @staticmethod + def tree() -> 'VmError': + return VmError('fee descendant_grant tree') + @staticmethod + def external() -> 'VmError': + return VmError('fee descendant_grant external') + class _VmErrorFee: @staticmethod def below_minimum() -> 'VmError': @@ -234,6 +245,9 @@ def too_many_rounds() -> 'VmError': @staticmethod def no_matching_allocation() -> '_VmErrorFeeNoMatchingAllocation': return _VmErrorFeeNoMatchingAllocation() + @staticmethod + def descendant_grant() -> '_VmErrorFeeDescendantGrant': + return _VmErrorFeeDescendantGrant() class _VmErrorEvm: @staticmethod diff --git a/runners/genlayer-py-std/tests/test_message_allocation.py b/runners/genlayer-py-std/tests/test_message_allocation.py new file mode 100644 index 00000000..cd4e437b --- /dev/null +++ b/runners/genlayer-py-std/tests/test_message_allocation.py @@ -0,0 +1,342 @@ +import types +import typing +from collections import UserList + +import genlayer as gl +import genlayer.calldata as calldata +import genlayer.contract as contract +import pytest +from genlayer.chain import InternalMessageParams +from genlayer.message_allocation import ( + ANY_METHOD, + ExternalAllocation, + InternalAllocation, + UseBalanceParams, + _resolve_call_key, +) +from genlayer.types import Address, Keccak256 + + +def params() -> InternalMessageParams: + return InternalMessageParams(5, 10, 100, [0], 1, 10**18, 10**18) + + +def test_message_allocation_module_is_available_from_package(): + assert gl.message_allocation.InternalAllocation is InternalAllocation + assert 'message_allocation' in gl.__all__ + + +def test_account_funding_type_hints_resolve(): + for account in (gl.chain.IAccount, gl.chain.Account): + assert ( + typing.get_type_hints(account.emit_transfer)['use_balance'] + == UseBalanceParams | None + ) + + +def test_call_key_resolution_matches_rust_sdk(): + assert _resolve_call_key(None) == ANY_METHOD + assert _resolve_call_key(bytes(32)) == bytes(32) + assert _resolve_call_key('') == bytes(32) + assert _resolve_call_key(b'\x07' * 32) == b'\x07' * 32 + assert _resolve_call_key('run') == b'run' + bytes(29) + + name = 'x' * 32 + expected = bytearray(Keccak256(name.encode()).digest()) + expected[-1] |= 1 + assert _resolve_call_key(name) == bytes(expected) + assert ANY_METHOD == Keccak256(b'').digest() + + +@pytest.mark.parametrize('invalid', [b'', b'1' * 4, b'1' * 31, b'1' * 33, 7, False]) +def test_call_key_resolution_rejects_invalid_values(invalid): + with pytest.raises((TypeError, ValueError)): + _resolve_call_key(invalid) + + +@pytest.mark.parametrize('name', ['a' * 31, 'a' * 32, 'é' * 15, 'é' * 16, 'é' * 40]) +def test_internal_call_key_uses_utf8_byte_length(name): + raw = name.encode() + if len(raw) < 32: + expected = raw + bytes(32 - len(raw)) + else: + expected = bytearray(Keccak256(raw).digest()) + expected[-1] |= 1 + expected = bytes(expected) + assert _resolve_call_key(name) == expected + + +@pytest.mark.parametrize('kind', ['call', 'transfer', 'deploy']) +@pytest.mark.parametrize('external', [False, True]) +@pytest.mark.parametrize( + 'key, expected', + [ + (None, ANY_METHOD), + (ANY_METHOD, ANY_METHOD), + (bytes(32), bytes(32)), + (bytes(range(32)), bytes(range(32))), + ], +) +def test_allocation_keys_survive_every_emission_path( + monkeypatch, kind, external, key, expected +): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + allocation = ( + ExternalAllocation(Address.ZERO, key, gl.chain.ExternalMessageParams(1, 1), 1) + if external + else InternalAllocation(Address.ZERO, key, params(), 100) + ) + funding = UseBalanceParams(params(), [allocation]) + proxy = contract.get_at(Address.ZERO) + if kind == 'call': + proxy.emit(funding).run() + elif kind == 'transfer': + proxy.emit_transfer(1, funding) + else: + contract.deploy(funding, code=b'code') + message = next(iter(calldata.decode(calls.pop()).values())) + assert message['descendants'][0]['call_key'] == expected + assert message['descendants'][0]['parent_index'] == 2**256 - 1 + + +@pytest.mark.parametrize('selector', [bytes(4), bytes.fromhex('a9059cbb'), b'\xff' * 4]) +@pytest.mark.parametrize('kind', ['call', 'transfer', 'deploy']) +def test_external_allocation_pads_selector_on_the_right(monkeypatch, selector, kind): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + node = ExternalAllocation( + Address.ZERO, selector, gl.chain.ExternalMessageParams(1, 1), 1 + ) + funding = UseBalanceParams(params(), [node]) + proxy = contract.get_at(Address.ZERO) + if kind == 'call': + proxy.emit(funding).run() + elif kind == 'transfer': + proxy.emit_transfer(1, funding) + else: + contract.deploy(funding, code=b'code') + message = next(iter(calldata.decode(calls.pop()).values())) + assert message['descendants'][0]['call_key'] == selector + bytes(28) + + +@pytest.mark.parametrize( + 'invalid', + [ + b'', + b'1', + b'123', + b'12345', + b'1' * 31, + b'1' * 33, + '', + 'transfer', + 'transfer(address,uint256)', + 7, + False, + bytearray(4), + memoryview(bytes(4)), + ], +) +def test_external_allocation_rejects_invalid_keys_before_emission(monkeypatch, invalid): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + node = ExternalAllocation( + Address.ZERO, invalid, gl.chain.ExternalMessageParams(1, 1), 1 + ) + with pytest.raises((TypeError, ValueError)): + contract.get_at(Address.ZERO).emit(UseBalanceParams(params(), [node])).run() + assert calls == [] + + +def test_allocations_encode_call_keys_and_shapes(): + internal = InternalAllocation( + Address.ZERO, + 'run', + params(), + 300, + on='decided', + children=[], + ) + external = ExternalAllocation( + Address.ZERO, + ANY_METHOD, + gl.chain.ExternalMessageParams(200_000, 10**9), + 200_000_000_000_000, + ) + + internal_value = internal.__to_calldata__() + assert internal_value['call_key'] == b'run' + bytes(29) + assert internal_value['on'] == 'decided' + assert 'children' not in internal_value + + external_value = external.__to_calldata__() + assert external_value['call_key'] == ANY_METHOD + assert 'on' not in external_value + assert 'children' not in external_value + + +class Zero(int): + pass + + +@pytest.mark.parametrize('descendants', [None, 0, Zero(0), [], (), UserList()]) +def test_closed_descendants_are_omitted_from_emit(monkeypatch, descendants): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + + contract.get_at(Address.ZERO).emit( + UseBalanceParams(fee_params=params(), descendants=descendants), + ).run() + + message = calldata.decode(calls.pop())['EmitInternalMessage'] + assert 'descendants' not in message + + +def test_open_and_pinned_descendants_are_forwarded(monkeypatch): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + proxy = contract.get_at(Address.ZERO) + + proxy.emit(use_balance=UseBalanceParams(params(), descendants=300)).run() + open_message = calldata.decode(calls.pop())['EmitInternalMessage'] + assert open_message['descendants'] == 300 + + root = InternalAllocation(Address.ZERO, None, params(), 300) + proxy.emit(UseBalanceParams(params(), descendants=[root])).run() + pinned_message = calldata.decode(calls.pop())['EmitInternalMessage'] + assert pinned_message['descendants'][0]['call_key'] == ANY_METHOD + assert pinned_message['descendants'][0]['parent_index'] == 2**256 - 1 + + +def test_deploy_forwards_descendants(monkeypatch): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + + contract.deploy( + UseBalanceParams(params(), descendants=300), + code=b'code', + ) + + message = calldata.decode(calls.pop())['EmitInternalDeployMessage'] + assert message['descendants'] == 300 + + +def test_bool_descendants_are_rejected(monkeypatch): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + + with pytest.raises(TypeError, match='bool'): + contract.get_at(Address.ZERO).emit( + UseBalanceParams(params(), descendants=False) + ).run() + + with pytest.raises(TypeError, match='bool'): + contract.deploy(UseBalanceParams(params(), descendants=False), code=b'code') + assert calls == [] + + +@pytest.mark.parametrize('keyword', [False, True]) +@pytest.mark.parametrize( + 'kind', ['call', 'transfer', 'deploy', 'account_transfer', 'self_transfer'] +) +def test_balance_parameter_can_be_positional_or_keyword(monkeypatch, keyword, kind): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + balance = UseBalanceParams(params()) + args, kwargs = ((), {'use_balance': balance}) if keyword else ((balance,), {}) + proxy = contract.get_at(Address.ZERO) + if kind == 'call': + proxy.emit(*args, **kwargs).run() + elif kind == 'transfer': + proxy.emit_transfer(1, *args, **kwargs) + elif kind == 'account_transfer': + gl.chain.Account(Address.ZERO).emit_transfer(1, *args, **kwargs) + elif kind == 'self_transfer': + monkeypatch.setattr(gl.message, 'contract_address', Address.ZERO, raising=False) + with pytest.warns(UserWarning, match='transfer to self'): + contract.Contract().emit_transfer(1, *args, **kwargs) + else: + assert contract.deploy(*args, code=b'code', **kwargs) is None + message = next(iter(calldata.decode(calls.pop()).values())) + assert message['use_balance'] is True + assert message['fee_params']['rotations'] == [0] + assert 'descendants' not in message + + +def test_sender_funding_omits_balance_fields(monkeypatch): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + contract.get_at(Address.ZERO).emit().run() + message = calldata.decode(calls.pop())['EmitInternalMessage'] + assert not {'use_balance', 'fee_params', 'descendants'} & message.keys() + with pytest.raises(TypeError, match='UseBalanceParams'): + contract.get_at(Address.ZERO).emit(True).run() + + +@pytest.mark.parametrize('sequence', [list, tuple, UserList]) +def test_descendant_tree_flattens_in_preorder_without_mutation(monkeypatch, sequence): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + leaf = InternalAllocation(Address.ZERO, 'leaf', params(), 10) + child = InternalAllocation(Address.ZERO, 'child', params(), 20, children=[leaf]) + root = InternalAllocation(Address.ZERO, 'root', params(), 30, children=[child, leaf]) + external = ExternalAllocation( + Address.ZERO, None, gl.chain.ExternalMessageParams(1, 1), 1 + ) + balance = UseBalanceParams(params(), sequence([root, external])) + for _ in range(2): + contract.get_at(Address.ZERO).emit(balance).run() + flat = calldata.decode(calls.pop())['EmitInternalMessage']['descendants'] + assert [node['parent_index'] for node in flat] == [2**256 - 1, 0, 1, 0, 2**256 - 1] + assert all('children' not in node for node in flat) + assert root.children == [child, leaf] + + +@pytest.mark.parametrize('sequence', [list, tuple, UserList]) +def test_cyclic_descendant_tree_is_bounded(monkeypatch, sequence): + calls = [] + monkeypatch.setattr( + contract, 'wasi', types.SimpleNamespace(gl_call=calls.append), raising=False + ) + root = InternalAllocation(Address.ZERO, None, params(), 1) + root.children.append(root) + with pytest.raises(ValueError, match='1024'): + contract.get_at(Address.ZERO).emit( + UseBalanceParams(params(), sequence([root])) + ).run() + assert calls == [] + + +@pytest.mark.parametrize( + 'descendants', ['', 'x', b'', b'x', bytearray(), bytearray(b'x')] +) +def test_string_descendants_are_rejected(descendants): + with pytest.raises(TypeError, match='str, bytes, or bytearray'): + contract._balance_fields(UseBalanceParams(params(), descendants)) + + +@pytest.mark.parametrize('sequence', [list, tuple, UserList]) +def test_descendant_sequences_reject_non_allocations(sequence): + with pytest.raises(TypeError, match='allocation objects'): + contract._balance_fields(UseBalanceParams(params(), sequence([1]))) diff --git a/runners/genlayer-py-std/tests/test_storage_core.py b/runners/genlayer-py-std/tests/test_storage_core.py index f44de1d6..92a123b1 100644 --- a/runners/genlayer-py-std/tests/test_storage_core.py +++ b/runners/genlayer-py-std/tests/test_storage_core.py @@ -5,10 +5,35 @@ VLA, Indirection, InmemManager, + ZeroManager, ) from genlayer.types import u32 +def test_zero_manager_is_singleton(): + manager = ZeroManager() + assert manager is ZeroManager() + slot = manager.get_store_slot(0) + assert slot.id == bytes(32) + assert manager.get_store_slot(bytes([1]) * 32).id == bytes([1]) * 32 + indirect = slot.indirect(100).indirect(200) + assert indirect.manager is manager + assert indirect.read(100, 32) == bytes(32) + + +@pytest.mark.parametrize('length', [0, 1, 32, 4096]) +def test_zero_manager_reads_ignore_offset(length): + slot = ZeroManager().get_store_slot(0) + assert slot.read(2**32 - 1, length) == bytes(length) + + +def test_zero_manager_rejects_writes(): + slot = ZeroManager().get_store_slot(0) + with pytest.raises(TypeError, match='read-only'): + slot.write(0, b'nonzero') + assert slot.read(0, 7) == bytes(7) + + def new_vla(): td = _storage_build(_BuilderCtx.empty(), VLA[u32]) man = InmemManager() diff --git a/runners/genlayer-py-std/tests/test_storage_to_calldata.py b/runners/genlayer-py-std/tests/test_storage_to_calldata.py index bfc07d59..7f2e97db 100644 --- a/runners/genlayer-py-std/tests/test_storage_to_calldata.py +++ b/runners/genlayer-py-std/tests/test_storage_to_calldata.py @@ -54,6 +54,18 @@ def test_dataclass(): } +@dataclass +class EncodableDataclass(calldata.CalldataEncodable): + value: int + + def __to_calldata__(self): + return self.value + 1 + + +def test_dataclass_calldata_encodable_uses_custom_encoding(): + assert calldata.decode(calldata.encode(EncodableDataclass(10))) == 11 + + class Strange: def __to_calldata__(self): return 11 diff --git a/runners/genlayer-py-std/tests/test_storage_tree_map.py b/runners/genlayer-py-std/tests/test_storage_tree_map.py index 8935fae3..1dbe490f 100644 --- a/runners/genlayer-py-std/tests/test_storage_tree_map.py +++ b/runners/genlayer-py-std/tests/test_storage_tree_map.py @@ -1,5 +1,9 @@ +import typing + import pytest -from genlayer.storage import TreeMap, inmem_allocate +from genlayer.storage import Array, DynArray, TreeMap, allow, inmem_allocate +from genlayer.storage.core import Indirection, Slot +from genlayer.types import u32 def new_map(): @@ -145,6 +149,40 @@ def test_assign(): same_iter(sorted(m.items()), sorted(r.items())) +@pytest.mark.parametrize('separate_view', [False, True]) +@pytest.mark.parametrize('values', [{}, {'a': '1', 'b': '2', 'c': '3'}]) +def test_assign_same_storage_is_noop(separate_view, values, monkeypatch): + m = new_map().assign(values) + source = m + if separate_view: + slot = m._storage_slot + source = Slot(slot.id, slot.manager).cast(TreeMap[str, str], m._off) + assert source is not m + + def unexpected_write(*args): + pytest.fail('same-storage assignment must not write') + + monkeypatch.setattr(type(m._storage_slot.manager), 'do_write', unexpected_write) + assert m.assign(source) is m + assert dict(m.items()) == values + + +@pytest.mark.parametrize('location', ['manager', 'slot', 'offset']) +def test_assign_distinct_storage(location): + m = new_map().assign({'old': 'value'}) + slot = m._storage_slot + if location == 'manager': + source = new_map() + elif location == 'slot': + source = slot.indirect(100).cast(TreeMap[str, str], 0) + else: + source = slot.cast(TreeMap[str, str], m.__type_desc__.size) + values = {'a': '1', 'b': '2'} + source.assign(values) + assert m.assign(source) is m + assert dict(m.items()) == dict(source.items()) == values + + def test_compute_if_absent_missing(): m = new_map() result = m.compute_if_absent('k', lambda: 'new_val') @@ -173,12 +211,134 @@ def fail(): assert list(m.items()) == [('before', 'value')] +@pytest.mark.parametrize('separate_view', [False, True]) +@pytest.mark.parametrize('values', [{}, {'existing': 'value'}]) +@pytest.mark.parametrize( + 'operation', + ['insert', 'overwrite', 'delete', 'clear', 'assign', 'default', 'compute'], +) +def test_supplier_cannot_mutate_same_map(separate_view, values, operation): + m = new_map().assign(values) + alias = m + if separate_view: + slot = m._storage_slot + alias = Slot(slot.id, slot.manager).cast(TreeMap[str, str], m._off) + + def supplier(): + if operation == 'insert': + alias['other'] = 'new' + elif operation == 'overwrite': + alias['existing'] = 'new' + elif operation == 'delete': + del alias['existing'] + elif operation == 'clear': + alias.clear() + elif operation == 'assign': + alias.assign({'other': 'new'}) + elif operation == 'default': + alias.get_or_insert_default('other') + else: + alias.compute_if_absent('other', lambda: 'new') + return 'result' + + with pytest.raises(RuntimeError, match='supplier callback'): + m.compute_if_absent('missing', supplier) + assert dict(m.items()) == values + assert len(m) == len(values) + assert m.compute_if_absent('missing', lambda: 'result') == 'result' + + +def test_supplier_can_read_same_map_and_mutate_other_map(): + m = new_map().assign({'existing': 'value'}) + other = new_map() + + def supplier(): + assert m['existing'] == 'value' + assert m.get_or_insert_default('existing') == 'value' + assert m.compute_if_absent('existing', lambda: pytest.fail('called')) == 'value' + other.compute_if_absent('key', lambda: 'other') + return 'result' + + assert m.compute_if_absent('missing', supplier) == 'result' + assert dict(m.items()) == {'existing': 'value', 'missing': 'result'} + assert dict(other.items()) == {'key': 'other'} + + +def test_supplier_guard_is_released_after_exception(): + m = new_map() + + def supplier(): + raise ValueError('supplier failed') + + with pytest.raises(ValueError, match='supplier failed'): + m.compute_if_absent('key', supplier) + m['key'] = 'value' + assert dict(m.items()) == {'key': 'value'} + + def test_get_or_insert_default(): m = new_map() m.get_or_insert_default('k') assert 'k' in m +@pytest.mark.parametrize('reuse', ['last', 'free', 'clear']) +@pytest.mark.parametrize('typ, old, default', [(u32, 100, 0), (str, 'old', '')]) +def test_default_initializes_recycled_value(reuse, typ, old, default): + m = inmem_allocate(TreeMap[str, typ]) + m['old'] = old + if reuse == 'free': + m['keep'] = old + if reuse == 'clear': + m.clear() + else: + del m['old'] + assert m.get_or_insert_default('new') == default + assert m['new'] == default + if reuse == 'free': + assert m['keep'] == old + + +@allow +class DefaultValue: + number: u32 + text: str + fixed: Array[u32, typing.Literal[2]] + items: DynArray[str] + mapping: TreeMap[str, u32] + indirect: Indirection[u32] + + +@pytest.mark.parametrize('reuse', ['last', 'free', 'clear']) +def test_default_initializes_recycled_compound_value(reuse): + m = inmem_allocate(TreeMap[str, DefaultValue]) + old = m.get_or_insert_default('old') + old.number = 100 + old.text = 'old' + old.fixed = [3, 4] + old.items.append('old') + old.mapping['old'] = 100 + old.indirect.set(100) + if reuse == 'free': + m.get_or_insert_default('keep').number = 200 + if reuse == 'clear': + m.clear() + else: + del m['old'] + value = m.get_or_insert_default('new') + assert value.number == 0 + assert value.text == '' + assert list(value.fixed) == [0, 0] + assert list(value.items) == [] + assert dict(value.mapping.items()) == {} + assert len(value.mapping) == 0 + assert value.indirect.get() == 0 + value.mapping['new'] = 5 + assert dict(value.mapping.items()) == {'new': 5} + if reuse == 'free': + assert m['keep'].number == 200 + + def test_get_or_insert_default_existing(): m = new_map() m['k'] = 'val' diff --git a/runners/genlayer-py-std/tests/test_storage_vec.py b/runners/genlayer-py-std/tests/test_storage_vec.py index d950b5fb..b8c62157 100644 --- a/runners/genlayer-py-std/tests/test_storage_vec.py +++ b/runners/genlayer-py-std/tests/test_storage_vec.py @@ -1,7 +1,7 @@ import pytest from genlayer.storage import DynArray, allow from genlayer.storage._internal.generate import _BuilderCtx, _storage_build -from genlayer.storage.core import ROOT_SLOT_ID, InmemManager +from genlayer.storage.core import ROOT_SLOT_ID, InmemManager, Slot from genlayer.types import u8, u32 from .common import SameOp @@ -99,6 +99,40 @@ def test_setitem_slice(idx: slice): same_iter(lx, r) +@pytest.mark.parametrize( + 'idx, count', + [ + (slice(0, 5, 2), 3), + (slice(None, None, 3), 4), + (slice(1, 10, 4), 3), + (slice(9, 2, -3), 3), + (slice(None, None, -1), 10), + ], +) +def test_setitem_extended_slice(idx: slice, count: int): + lx = new_vec() + r: list[str] = [str(x) for x in range(10)] + lx[:] = r + + x = [str(10 + i) for i in range(count)] + r[idx] = x + lx[idx] = x + same_iter(lx, r) + + +@pytest.mark.parametrize( + 'idx', [slice(0, 5, 2), slice(None, None, -1), slice(9, 2, -3)] +) +def test_setitem_extended_slice_size_mismatch(idx: slice): + lx = new_vec() + r: list[str] = [str(x) for x in range(10)] + lx[:] = r + + with pytest.raises(ValueError): + lx[idx] = ['a', 'b'] + same_iter(lx, r) + + @pytest.mark.parametrize( 'idx', [ @@ -223,6 +257,34 @@ def test_assign_empty(): assert len(lx) == 0 +@pytest.mark.parametrize('separate_view', [False, True]) +@pytest.mark.parametrize('values', [[], ['a', 'b', 'c']]) +def test_assign_same_storage_is_noop(separate_view, values): + lx = new_vec().assign(values) + source = lx + if separate_view: + slot = lx._storage_slot + source = Slot(slot.id, slot.manager).cast(DynArray[str], lx._off) + assert source is not lx + assert lx.assign(source) is lx + assert list(lx) == values + + +@pytest.mark.parametrize('location', ['manager', 'slot', 'offset']) +def test_assign_distinct_storage(location): + lx = new_vec().assign(['a']) + slot = lx._storage_slot + if location == 'manager': + source = new_vec() + elif location == 'slot': + source = slot.indirect(100).cast(DynArray[str], 0) + else: + source = slot.cast(DynArray[str], 4) + source.assign(['b', 'c']) + lx.assign(source) + assert list(lx) == list(source) == ['b', 'c'] + + def test_append_new_get(): lx = new_vec() lx.append('hello') @@ -254,6 +316,75 @@ def __index__(self) -> int: return self.value +@pytest.mark.parametrize('operation', ['get', 'set', 'delete']) +@pytest.mark.parametrize('index', [0, -1, 3, -4]) +def test_item_operations_accept_index_protocol(operation, index): + lx = new_vec().assign(['a', 'b', 'c']) + expected = ['a', 'b', 'c'] + + def apply(arr, idx): + if operation == 'get': + return arr[idx] + if operation == 'set': + arr[idx] = 'x' + else: + del arr[idx] + + try: + result = apply(expected, index) + except IndexError: + with pytest.raises(IndexError): + apply(lx, Index(index)) + else: + assert apply(lx, Index(index)) == result + assert list(lx) == expected + + +@pytest.mark.parametrize('operation', ['get', 'set', 'delete']) +@pytest.mark.parametrize('index', [1.0, '1', None, Index('1')]) +def test_item_operations_reject_invalid_indices(operation, index): + lx = new_vec().assign(['a', 'b', 'c']) + with pytest.raises(TypeError): + if operation == 'get': + lx[index] + elif operation == 'set': + lx[index] = 'x' + else: + del lx[index] + assert list(lx) == ['a', 'b', 'c'] + + +@pytest.mark.parametrize('step', [1, 2, -1, -2, 0]) +@pytest.mark.parametrize('count', [0, 2, 3, 4]) +def test_setitem_slice_accepts_index_step(step, count): + lx = new_vec() + r = ['a', 'b', 'c'] + lx.assign(r) + idx = slice(None, None, Index(step)) + values = [str(i) for i in range(count)] + try: + r[idx] = values + except ValueError: + with pytest.raises(ValueError): + lx[idx] = values + else: + lx[idx] = values + assert list(lx) == r + + +def test_setitem_slice_normalizes_step_once(): + class Once: + def __index__(self): + assert not getattr(self, 'called', False) + self.called = True + return 1 + + lx = new_vec() + lx.assign(['a', 'b', 'c']) + lx[:: Once()] = ['x', 'y'] + assert list(lx) == ['x', 'y'] + + def test_insert_and_pop_accept_index_protocol(): lx = new_vec() lx.assign(['a', 'c']) diff --git a/runners/support/versions/current.nix b/runners/support/versions/current.nix index 9bf5e8db..597f9a1c 100644 --- a/runners/support/versions/current.nix +++ b/runners/support/versions/current.nix @@ -49,7 +49,7 @@ let }; genlayer-std = { - hash = "sha256-n/ABVbRLtEvOi72uVspaLmjhe0c1T5+G6/q6CddGoqg="; + hash = "sha256-+d+0LvZ2pD5WTUZqXJevvtw8fRWmrkrbjxXbuuSn/KE="; depends = [ top ]; @@ -83,7 +83,7 @@ let wrappers = { __prefix = ""; py-genlayer = { - hash = "sha256-LLzIOJdExDIYUtLAtL/O8HKb/SJGfiqvDU0gTPbwFes="; + hash = "sha256-WpfLJ0M8uJgSQlsZCoSQN0/U5C87c0id1N/OMtvk/1Q="; depends = [ cpython pyLibs.cloudpickle @@ -91,7 +91,7 @@ let ]; }; py-genlayer-multi = { - hash = "sha256-er0/qwaOCui+gDyVqhkux01dpNynwqWFufy1FbIYcOg="; + hash = "sha256-E83q9vT/4BbRmVSLQUwrCuFnB8NBQePuNEUE53GbgEY="; depends = [ cpython pyLibs.cloudpickle diff --git a/tests/integration/balance/balance/balance.0.hash b/tests/integration/balance/balance/balance.0.hash index d6eec053..dbbe6d54 100644 --- a/tests/integration/balance/balance/balance.0.hash +++ b/tests/integration/balance/balance/balance.0.hash @@ -1 +1 @@ -dKsQwDDG64vYDJmWsugWRsDvrJ6WLSJ5DfenXKEuWBI= +si22T8+0w0ySjiRDdKET9oksKIn1PTMzJ51TgX6q3xY= diff --git a/tests/integration/balance/balance/balance.0_0.hash b/tests/integration/balance/balance/balance.0_0.hash index 03543a5e..2c481317 100644 --- a/tests/integration/balance/balance/balance.0_0.hash +++ b/tests/integration/balance/balance/balance.0_0.hash @@ -1 +1 @@ -JB0Oezep4QthkURSOtzNGrNrvFcSn9rplyBwMLTlshE= +WUdowaTUITkIAlPY9NSUR//vToOsF4A9IkyoUIw/u+A= diff --git a/tests/integration/balance/balance_eth/balance_eth.0.hash b/tests/integration/balance/balance_eth/balance_eth.0.hash index 97407ce5..895ed674 100644 --- a/tests/integration/balance/balance_eth/balance_eth.0.hash +++ b/tests/integration/balance/balance_eth/balance_eth.0.hash @@ -1 +1 @@ -qH2cZJm4nD+5nR5UFQz0FYGrfpYd7yq8XuVnKxDc7QU= +omkbKwDr0PeQB8c3XIK49eESFPZKHrb5/Dw6K/iMPqU= diff --git a/tests/integration/balance/balance_eth/balance_eth.0_0.hash b/tests/integration/balance/balance_eth/balance_eth.0_0.hash index 07305bfb..b90455ba 100644 --- a/tests/integration/balance/balance_eth/balance_eth.0_0.hash +++ b/tests/integration/balance/balance_eth/balance_eth.0_0.hash @@ -1 +1 @@ -v9hp/eyxuszuAVgkdTrPYrRVwD5y7zSHdqNew99KHQE= +Ivo2KCH/rP9tF26KpQV+A0cUzR8mMWjOEJPBZL00cDc= diff --git a/tests/integration/balance/sandbox_overspend/sandbox_overspend.0.hash b/tests/integration/balance/sandbox_overspend/sandbox_overspend.0.hash index 11c933c1..5d40ae59 100644 --- a/tests/integration/balance/sandbox_overspend/sandbox_overspend.0.hash +++ b/tests/integration/balance/sandbox_overspend/sandbox_overspend.0.hash @@ -1 +1 @@ -om9ZwsG6LO2qGDr1CzrEZ4zxfPbOTqt3etru5kiNWps= +05JMUZIJ2qLUvKayximiZpydPi5o9Hv52594vYChhBA= diff --git a/tests/integration/balance/sandbox_overspend_2/sandbox_overspend_2.0.hash b/tests/integration/balance/sandbox_overspend_2/sandbox_overspend_2.0.hash index 7aecabac..f63c631f 100644 --- a/tests/integration/balance/sandbox_overspend_2/sandbox_overspend_2.0.hash +++ b/tests/integration/balance/sandbox_overspend_2/sandbox_overspend_2.0.hash @@ -1 +1 @@ -02uyKWwSjte3j/u3l7ze7PAwLl9h+0rfQ8vwM3eYZQI= +bVuwbWzWURJ7JPoi1ZQDDcno1t3GEIiqW7YHNdFirXI= diff --git a/tests/integration/bench/read_tree_map/read_tree_map.0.hash b/tests/integration/bench/read_tree_map/read_tree_map.0.hash index b0950f0e..9fab169b 100644 --- a/tests/integration/bench/read_tree_map/read_tree_map.0.hash +++ b/tests/integration/bench/read_tree_map/read_tree_map.0.hash @@ -1 +1 @@ -CJSQAdQm0SuGm2wA/pFPg9K9BMFdzUMoQ7vKwd3/f0s= +ZSHDfw7HZsDV2YpPHb0pv9kvnNeWEezWLTbT1cwDUos= diff --git a/tests/integration/bench/read_tree_map/read_tree_map.0_0.hash b/tests/integration/bench/read_tree_map/read_tree_map.0_0.hash index 6eb05f29..ee780aed 100644 --- a/tests/integration/bench/read_tree_map/read_tree_map.0_0.hash +++ b/tests/integration/bench/read_tree_map/read_tree_map.0_0.hash @@ -1 +1 @@ -Xa+M0l6W+sp7R6pCo7QIx6zeUzv7A+TZlBaFtOrpJ6g= +e0WLaq0WefVc25UpHpT79j/Ye+6IgPlkHfYrLOXREcU= diff --git a/tests/integration/event/post_event/post_event.0.hash b/tests/integration/event/post_event/post_event.0.hash index 6ae1f093..3b4a2c97 100644 --- a/tests/integration/event/post_event/post_event.0.hash +++ b/tests/integration/event/post_event/post_event.0.hash @@ -1 +1 @@ -tqOXw5Xs8d6J4+DRqI7ksnUpQBjn/HS4/R+qEoyTVZI= +oM9KeUgUeRjECW2Q3HOm6L33uqXgMP2vWJfY4fE11YQ= diff --git a/tests/integration/exploit/call_wasi_extra/call_wasi_extra.0.hash b/tests/integration/exploit/call_wasi_extra/call_wasi_extra.0.hash index 1c596046..c5e156e0 100644 --- a/tests/integration/exploit/call_wasi_extra/call_wasi_extra.0.hash +++ b/tests/integration/exploit/call_wasi_extra/call_wasi_extra.0.hash @@ -1 +1 @@ -Xx9Lc+4PTElh1TsTuaB28mfN5u6AMBXgo0raJcW4fbU= +tQGOmktcbOOj6Ve1YHat7UDzAz8A5b8wViKxXR2lxso= diff --git a/tests/integration/exploit/disagree_in_sandbox/disagree_in_sandbox.0.hash b/tests/integration/exploit/disagree_in_sandbox/disagree_in_sandbox.0.hash index e4762e7e..c0fb1c48 100644 --- a/tests/integration/exploit/disagree_in_sandbox/disagree_in_sandbox.0.hash +++ b/tests/integration/exploit/disagree_in_sandbox/disagree_in_sandbox.0.hash @@ -1 +1 @@ -BSoi89kEgr1HPI/mg5qcYr6zfaqhe+2NdlPKOLk2rRk= +vAgFzc/SGESRTjKdpwsHCmN6EjV0akVxOMRB+Hzkc+s= diff --git a/tests/integration/exploit/fork_bomb/fork_bomb.0.hash b/tests/integration/exploit/fork_bomb/fork_bomb.0.hash index 9c0bca56..cdef943c 100644 --- a/tests/integration/exploit/fork_bomb/fork_bomb.0.hash +++ b/tests/integration/exploit/fork_bomb/fork_bomb.0.hash @@ -1 +1 @@ -vvPMq7o5QTLPxIYg7651+q+7aXMLjhWbw4Tx4FEhqSo= +RxFzqDW/D94nbnwmaEwC50KRfzvDzGvgo5vMiOxQUUo= diff --git a/tests/integration/exploit/nested_memory_limit/nested_memory_limit.0.hash b/tests/integration/exploit/nested_memory_limit/nested_memory_limit.0.hash index fe1300ac..e174f195 100644 --- a/tests/integration/exploit/nested_memory_limit/nested_memory_limit.0.hash +++ b/tests/integration/exploit/nested_memory_limit/nested_memory_limit.0.hash @@ -1 +1 @@ -1QLBgj6xIMZgo1xObGui/NTsnMh/F3I3PT5dek3mFPg= +01l29RLmp1i1fCUqbLRfBrZRXmg59AEWtRlTHad3s60= diff --git a/tests/integration/exploit/oom/oom.0.hash b/tests/integration/exploit/oom/oom.0.hash index dac54305..c718e469 100644 --- a/tests/integration/exploit/oom/oom.0.hash +++ b/tests/integration/exploit/oom/oom.0.hash @@ -1 +1 @@ -+7AzEQmeamGw8S3s4CGby2XqWjCxyylb24v0THoas1c= +zvBHgjX0/FrUYE87b2TsTduF8UW3q6qDUQITUTXPygI= diff --git a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0.hash b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0.hash index f205fa1d..526f07d1 100644 --- a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0.hash +++ b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0.hash @@ -1 +1 @@ -eoDI7yfUoylCvaBrO5m4q/nBhv4NZaoUWuv86LogCnA= +jyZsUb+T/E/j1tVUUmgCnsbOP+vwUo7/4Y7v0EwXMkw= diff --git a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_0.hash b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_0.hash index 1f8567b8..abbfac08 100644 --- a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_0.hash +++ b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_0.hash @@ -1 +1 @@ -0Qx2PRlbU0o4mwKcN7JobA65WTiBCnaoFDRVgXwIhJs= +cPYxHvjq5wsousonsocNQrme2eiDBUMfm7ZdkLsT/1A= diff --git a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_1.hash b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_1.hash index 42f11300..f3027b90 100644 --- a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_1.hash +++ b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_1.hash @@ -1 +1 @@ -9z9wIk0RgVyNajrUHIxFmMKb1yGT0eR6muv8w01jQo4= +0/672F8nR3YlhmiVcu9r16hwtiZTqQk9tXFvvg4akt4= diff --git a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_2.hash b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_2.hash index cd640c65..22c58648 100644 --- a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_2.hash +++ b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_2.hash @@ -1 +1 @@ -ezzRALGWLsoZqZf8QGm8d0GKRQdC3rKZBScBa4r0bh0= +8s+ebb46GuF4DZ699Y4evSe7nkr94bA9O5GJV32bpTI= diff --git a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_3.hash b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_3.hash index 91b42c4c..0fbc306e 100644 --- a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_3.hash +++ b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_3.hash @@ -1 +1 @@ -OWOxplk93i6I4bcOl53QeGkLbTXnxYBv24GAlOwIlqU= +ZcBGamLKlXpPlz3Ag/9dkifnkSZtraZPVNSwNAmwefU= diff --git a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_4.hash b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_4.hash index ec44d296..7d592e5f 100644 --- a/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_4.hash +++ b/tests/integration/exploit/storage_distinct_pages/storage_distinct_pages.0_4.hash @@ -1 +1 @@ -48MzjghqE0W09IcwnHW262FTV3S+HDJnc/a2GY2jOtg= +mzTVpcRAMnqliXMCXK7qNtv029Sy/T5U0AUwQAjSyc4= diff --git a/tests/integration/exploit/storage_page_limit/storage_page_limit.0.hash b/tests/integration/exploit/storage_page_limit/storage_page_limit.0.hash index 13ccd8de..cc9e2c78 100644 --- a/tests/integration/exploit/storage_page_limit/storage_page_limit.0.hash +++ b/tests/integration/exploit/storage_page_limit/storage_page_limit.0.hash @@ -1 +1 @@ -d7KEc+/ItT4T3dxwb7C6v66rRs2GL+65BVYJey/EZRo= +agFoeSHiEu1DOwhsrPmUYnhUS7K2ugusPP2PEAkaR/k= diff --git a/tests/integration/exploit/storage_page_limit/storage_page_limit.0_0.hash b/tests/integration/exploit/storage_page_limit/storage_page_limit.0_0.hash index 3acd0deb..c9b34bed 100644 --- a/tests/integration/exploit/storage_page_limit/storage_page_limit.0_0.hash +++ b/tests/integration/exploit/storage_page_limit/storage_page_limit.0_0.hash @@ -1 +1 @@ -+jp7xkdIgYZNGWllBrb3lK2mo3wxdu0/Y20k02raCJQ= +SnWP7y1CU7oIRhuct70YXWoK9SadlvTF8LBji9iXMUk= diff --git a/tests/integration/exploit/storage_page_limit/storage_page_limit.0_1.hash b/tests/integration/exploit/storage_page_limit/storage_page_limit.0_1.hash index 6d3a3336..800ab39c 100644 --- a/tests/integration/exploit/storage_page_limit/storage_page_limit.0_1.hash +++ b/tests/integration/exploit/storage_page_limit/storage_page_limit.0_1.hash @@ -1 +1 @@ -c+0u8FsVvWA2gBAU2vafXyD7Ovly2blNZXeBIDcFQcw= +MSqhzWmdf7gXmtdjmJFoiEfLAlon75o7HVeycSV1zeA= diff --git a/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_ends_at_end.hash b/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_ends_at_end.hash index b72e3923..a0688da6 100644 --- a/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_ends_at_end.hash +++ b/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_ends_at_end.hash @@ -1 +1 @@ -E7gOF8wlfunUIlF9iOTToH24lIRu2tTHNvgJJWOqAak= +Czy1ev8qFRQYZEMRbXk2RDedkat7yxLOqvvlzoczPfo= diff --git a/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_last_byte.hash b/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_last_byte.hash index 2cc50001..98d254a9 100644 --- a/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_last_byte.hash +++ b/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_last_byte.hash @@ -1 +1 @@ -nVJ90W62kgEgELI1Jy7pPEOzzSxfahtPWfjRmMA+eRM= +ryl4i8eS9x0wZAuEEt4MfgxO9MX5AaxMMRwiPQyipS0= diff --git a/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_over_end.hash b/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_over_end.hash index 7d604879..0d570cad 100644 --- a/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_over_end.hash +++ b/tests/integration/exploit/storage_slot_edge/storage_slot_edge.read_over_end.hash @@ -1 +1 @@ -j1xF1iWHQKHsW1faeoUCnuJErgZUu7mMWk0KNKCcBbE= +IORi/1NAhNsO+rW/BaiFk+AdoKuOxjhjflXR+ofSN+c= diff --git a/tests/integration/exploit/storage_slot_edge/storage_slot_edge.write_last_byte.hash b/tests/integration/exploit/storage_slot_edge/storage_slot_edge.write_last_byte.hash index c5b0a34b..09b1af54 100644 --- a/tests/integration/exploit/storage_slot_edge/storage_slot_edge.write_last_byte.hash +++ b/tests/integration/exploit/storage_slot_edge/storage_slot_edge.write_last_byte.hash @@ -1 +1 @@ -v6j71MpLJmf3aMKaUMNST97y9qpdAs1t6oSi+8IMF3I= +ss88yMu2ImAKyLUThZ2TeGKZcEGRazCXoCrNOTCrGxk= diff --git a/tests/integration/exploit/storage_slot_edge/storage_slot_edge.write_over_end.hash b/tests/integration/exploit/storage_slot_edge/storage_slot_edge.write_over_end.hash index 54c9bc1b..6b562f2e 100644 --- a/tests/integration/exploit/storage_slot_edge/storage_slot_edge.write_over_end.hash +++ b/tests/integration/exploit/storage_slot_edge/storage_slot_edge.write_over_end.hash @@ -1 +1 @@ -Bt2WHBDLiR5FIV7xRj6gt+wtRIT+1i4T10s+ZnR4yyQ= +Z/HkocK8/aVVKqr6P2T09r+PaFkU9yjZoRj5lcEmQAE= diff --git a/tests/integration/hello-world/hello_world/hello_world.0.hash b/tests/integration/hello-world/hello_world/hello_world.0.hash index 6579999f..a2563692 100644 --- a/tests/integration/hello-world/hello_world/hello_world.0.hash +++ b/tests/integration/hello-world/hello_world/hello_world.0.hash @@ -1 +1 @@ -HyJKyoJMbYkdmoD9aFJX2lrSasN8gRENMuE3CXKGUXg= +F238W72HnA+vUjPbPdKPSyVnNniAC3fzqOEdLZl3bS0= diff --git a/tests/integration/hello-world/hello_world_class_nondet/hello_world_class_nondet.0.hash b/tests/integration/hello-world/hello_world_class_nondet/hello_world_class_nondet.0.hash index a9dc2275..0998760d 100644 --- a/tests/integration/hello-world/hello_world_class_nondet/hello_world_class_nondet.0.hash +++ b/tests/integration/hello-world/hello_world_class_nondet/hello_world_class_nondet.0.hash @@ -1 +1 @@ -iysUZumEEkK2cCrQ33c5epgxBZBiE27znLJsDN2xuK8= +DvjKd0DUriXezf7CaDouCsLXlAUzszdTrLQffLQOfUo= diff --git a/tests/integration/hello-world/trivial/trivial.0.hash b/tests/integration/hello-world/trivial/trivial.0.hash index a23006cf..f1e300c0 100644 --- a/tests/integration/hello-world/trivial/trivial.0.hash +++ b/tests/integration/hello-world/trivial/trivial.0.hash @@ -1 +1 @@ -OOoW7S/KsvxtIFT3n7iq1FLHyzArBMndb7AY2GaDdKE= +v60hAHMxc3Asm8jxYsekWsmmbqAt4unloc2I748mK/o= diff --git a/tests/integration/hello-world/trivial/trivial.0_0.hash b/tests/integration/hello-world/trivial/trivial.0_0.hash index 96e613c9..aca3af05 100644 --- a/tests/integration/hello-world/trivial/trivial.0_0.hash +++ b/tests/integration/hello-world/trivial/trivial.0_0.hash @@ -1 +1 @@ -mc5hmI11H/Z0rLfcyyQBGEiV+LxHULf/eMkDcU8obew= +SD5raKaqZpv/P4k6i//59AOmA82YP+m2kuFCysG9u4I= diff --git a/tests/integration/message/call_self_view/call_self_view.0.hash b/tests/integration/message/call_self_view/call_self_view.0.hash index e5a01548..76a1f303 100644 --- a/tests/integration/message/call_self_view/call_self_view.0.hash +++ b/tests/integration/message/call_self_view/call_self_view.0.hash @@ -1 +1 @@ -rz5cFXRtbTOkTK49x3P63xjHC8rDukxNuzeqnyngf3k= +iPe7S4Br6Y21jFI6Gy0o6hEdTFAr+CKdACr68Avt2eI= diff --git a/tests/integration/message/call_self_view_stack.0.hash b/tests/integration/message/call_self_view_stack.0.hash index 6cf7c2df..10b3d75a 100644 --- a/tests/integration/message/call_self_view_stack.0.hash +++ b/tests/integration/message/call_self_view_stack.0.hash @@ -1 +1 @@ -BwyEKSWKx0C3cgQoL8BB8VJgaqNXQRCGQ450sm20vQU= +IjZ0yJb7s1ec2WsxOjj+PzvpY6YneTA5KvSWy6th7Ow= diff --git a/tests/integration/message/call_self_view_stack.0_0.hash b/tests/integration/message/call_self_view_stack.0_0.hash index 1c2c67ac..dec0bb64 100644 --- a/tests/integration/message/call_self_view_stack.0_0.hash +++ b/tests/integration/message/call_self_view_stack.0_0.hash @@ -1 +1 @@ -4EE9pi3hZn+YgB7YuXVSZm+E8XM/CNORO2tTNJToOFA= +pR4+Hkda0o//aeEQie3JLpaMWXWkppLuz1GS7PMbWb0= diff --git a/tests/integration/message/call_view/call_view.0.hash b/tests/integration/message/call_view/call_view.0.hash index b1417e5e..6396130a 100644 --- a/tests/integration/message/call_view/call_view.0.hash +++ b/tests/integration/message/call_view/call_view.0.hash @@ -1 +1 @@ -ISND7FZIT5sxMGV7dQrnWVqbTYhOKelN1YWP/QvIx98= +LqnDl+H4Qi8XlGLzHkcQDZcDM8zUAGG9u+4b1ol/jTQ= diff --git a/tests/integration/message/call_view/call_view.0_0.hash b/tests/integration/message/call_view/call_view.0_0.hash index 9be88452..04a7abbc 100644 --- a/tests/integration/message/call_view/call_view.0_0.hash +++ b/tests/integration/message/call_view/call_view.0_0.hash @@ -1 +1 @@ -gN3O4gm9DgCOewSyOlZ993hCPHCuHGdBPQeng36lcCc= +QSsp9f2hPi3hZ5IWZS5U9nXv1E0B7mz3ZpBuZ6O0b0g= diff --git a/tests/integration/message/call_view/call_view.0_0_0.hash b/tests/integration/message/call_view/call_view.0_0_0.hash index 9b364bb1..5ef7ef2a 100644 --- a/tests/integration/message/call_view/call_view.0_0_0.hash +++ b/tests/integration/message/call_view/call_view.0_0_0.hash @@ -1 +1 @@ -zNbO+FI8BSkXWBCaDbrt1yfl+O4te9/Ghq6Q2LJ+ifM= +i0lF9ohpWGYPwjMISn/I90hKfkmMijGnoKVHd0KioGE= diff --git a/tests/integration/message/call_view/call_view_iface.0.hash b/tests/integration/message/call_view/call_view_iface.0.hash index b1417e5e..6396130a 100644 --- a/tests/integration/message/call_view/call_view_iface.0.hash +++ b/tests/integration/message/call_view/call_view_iface.0.hash @@ -1 +1 @@ -ISND7FZIT5sxMGV7dQrnWVqbTYhOKelN1YWP/QvIx98= +LqnDl+H4Qi8XlGLzHkcQDZcDM8zUAGG9u+4b1ol/jTQ= diff --git a/tests/integration/message/call_view/call_view_iface.0_0.hash b/tests/integration/message/call_view/call_view_iface.0_0.hash index 57a61b44..d019403f 100644 --- a/tests/integration/message/call_view/call_view_iface.0_0.hash +++ b/tests/integration/message/call_view/call_view_iface.0_0.hash @@ -1 +1 @@ -Sm4aWTZEiv1V2hKklqyI7uWQdQzaSxEAkSDFvxLBAK4= +8Qg4OYCain+koToOzlqRzglFjzca0xRGmdFFul/m9bE= diff --git a/tests/integration/message/call_view/call_view_iface.0_0_0.hash b/tests/integration/message/call_view/call_view_iface.0_0_0.hash index cea0ff14..bcbfc3ac 100644 --- a/tests/integration/message/call_view/call_view_iface.0_0_0.hash +++ b/tests/integration/message/call_view/call_view_iface.0_0_0.hash @@ -1 +1 @@ -Owtnewllq67CD6T79RT2FQFkJnHEZwxKaskWV9DJFvg= +FThNVJm9O1GfYwrirOXRWDldlNbddKi0L2QpaaasnLI= diff --git a/tests/integration/message/call_view_committed/call_view_committed.0.hash b/tests/integration/message/call_view_committed/call_view_committed.0.hash index 57a152b7..8df9b57d 100644 --- a/tests/integration/message/call_view_committed/call_view_committed.0.hash +++ b/tests/integration/message/call_view_committed/call_view_committed.0.hash @@ -1 +1 @@ -T5o84cmlNrJs7gh6E/EZEacSCme5N9wp8uIVqX60KMY= +dKf0+m8sgUz8NnTzRRBeGNcIYJt9bCZOhmnSIWrZxmY= diff --git a/tests/integration/message/call_view_committed/call_view_committed.0_0.hash b/tests/integration/message/call_view_committed/call_view_committed.0_0.hash index 4bb721fc..7b854e41 100644 --- a/tests/integration/message/call_view_committed/call_view_committed.0_0.hash +++ b/tests/integration/message/call_view_committed/call_view_committed.0_0.hash @@ -1 +1 @@ -AoDTJjt7q4KgHwFcfnWHbY4QcK5diFM7tuRrasWA5Ck= +HlFexbNXOnB6L7XuV9Aoh5WAfv5fFH+qZdlANYJA1yY= diff --git a/tests/integration/message/call_view_emit/call_view_emit.0.hash b/tests/integration/message/call_view_emit/call_view_emit.0.hash index 515c2e4d..52bb577e 100644 --- a/tests/integration/message/call_view_emit/call_view_emit.0.hash +++ b/tests/integration/message/call_view_emit/call_view_emit.0.hash @@ -1 +1 @@ -0mxPo0hpToJgHXxXzV04+lcfP5ccXA2/2HqeP6fVj1o= +GkH+1qntHyLy0LXTkZYnAqetGIvKxu7dtl2VAsB1fZI= diff --git a/tests/integration/message/call_view_emit/call_view_emit.0_0.hash b/tests/integration/message/call_view_emit/call_view_emit.0_0.hash index fa8d3f83..4ef0abfd 100644 --- a/tests/integration/message/call_view_emit/call_view_emit.0_0.hash +++ b/tests/integration/message/call_view_emit/call_view_emit.0_0.hash @@ -1 +1 @@ -+qtP/3zBLJ0UE2rGhqueuvGo7+QfjrNxuLFCSMowRpk= +ickmgrZ2tOBE8Ct6vCbe6/EOj7kxu3kMb/lHh+XS1TA= diff --git a/tests/integration/message/call_view_emit/call_view_emit.0_0_0.hash b/tests/integration/message/call_view_emit/call_view_emit.0_0_0.hash index 958eb4f1..b8c16169 100644 --- a/tests/integration/message/call_view_emit/call_view_emit.0_0_0.hash +++ b/tests/integration/message/call_view_emit/call_view_emit.0_0_0.hash @@ -1 +1 @@ -Z17WDsnnXFyJr3+ytcPgM2SE0rzPNtYxkIdxAkIzNAQ= +UE10vvGcQH0cHYnuam+lC3E/YDEWdJp0M1q+k3/U0xU= diff --git a/tests/integration/message/catch_vm_error/catch_vm_error.0.hash b/tests/integration/message/catch_vm_error/catch_vm_error.0.hash index ff704733..1ab4e436 100644 --- a/tests/integration/message/catch_vm_error/catch_vm_error.0.hash +++ b/tests/integration/message/catch_vm_error/catch_vm_error.0.hash @@ -1 +1 @@ -zZgsldttAqc2Kh/MLdzVIrQQaMiuThVUZ5HS1hqoEmc= +Yrns5+ZcvRpWYtFR/ti7RoPJ3phrst2sNKulVnHjgLo= diff --git a/tests/integration/message/catch_vm_error/catch_vm_error.0_0.hash b/tests/integration/message/catch_vm_error/catch_vm_error.0_0.hash index cd1378a9..07694b9c 100644 --- a/tests/integration/message/catch_vm_error/catch_vm_error.0_0.hash +++ b/tests/integration/message/catch_vm_error/catch_vm_error.0_0.hash @@ -1 +1 @@ -5grTqWSnToKfCiY44bk4dr6v9zUP5q35HllEqHTzYDw= +PUYUfk0RFmPX6yWOZgNd9Y6i0Y7sQauaUkILf9yM/wk= diff --git a/tests/integration/message/catch_vm_error/catch_vm_error.0_0_0.hash b/tests/integration/message/catch_vm_error/catch_vm_error.0_0_0.hash index dd6bc919..ea4b9c37 100644 --- a/tests/integration/message/catch_vm_error/catch_vm_error.0_0_0.hash +++ b/tests/integration/message/catch_vm_error/catch_vm_error.0_0_0.hash @@ -1 +1 @@ -sPrewyS48rMi7IYcBgqiNaG1W8P8MXc1HOd2PkxuUXk= +FZCbdNwxhHUPGUGjfR2ScsypnQUERON/aTbDZptZzrk= diff --git a/tests/integration/message/deploy/deploy.0.hash b/tests/integration/message/deploy/deploy.0.hash index d29efe08..8145f94e 100644 --- a/tests/integration/message/deploy/deploy.0.hash +++ b/tests/integration/message/deploy/deploy.0.hash @@ -1 +1 @@ -BOj7XyVTFi2B/pS70PGkr56OqffrRmoJjEn6NngWW2E= +YUmVt101TVfeiMvKr6Ol2eYM8fDae30hHDEwxlUeU2Y= diff --git a/tests/integration/message/deploy_salt/deploy_salt.0.hash b/tests/integration/message/deploy_salt/deploy_salt.0.hash index 168982a3..8da30164 100644 --- a/tests/integration/message/deploy_salt/deploy_salt.0.hash +++ b/tests/integration/message/deploy_salt/deploy_salt.0.hash @@ -1 +1 @@ -E90VS+xq/RN7xpr6USgvdzPTb//P8sebB1W9lNv9lvQ= +tVbkaNKPTwC6gqpl8j0t+I25mmXNDtqdVzg4i/ApeIQ= diff --git a/tests/integration/message/eth_call_view/eth_call_view.0.hash b/tests/integration/message/eth_call_view/eth_call_view.0.hash index 0abc6270..782a80db 100644 --- a/tests/integration/message/eth_call_view/eth_call_view.0.hash +++ b/tests/integration/message/eth_call_view/eth_call_view.0.hash @@ -1 +1 @@ -DfdLUU3ZLZcZ6LNU0rVpiW6XpxowQ7EXo+n1yx+Vfbw= +IkwXqS96RLTAxOhTB/8Ym+3SJOSasSvbOmg5qYT4nm4= diff --git a/tests/integration/message/internal_below_min_timeunits/internal_below_min_timeunits.0.hash b/tests/integration/message/internal_below_min_timeunits/internal_below_min_timeunits.0.hash index 485e0beb..0364a34e 100644 --- a/tests/integration/message/internal_below_min_timeunits/internal_below_min_timeunits.0.hash +++ b/tests/integration/message/internal_below_min_timeunits/internal_below_min_timeunits.0.hash @@ -1 +1 @@ -X+1gF+C9/Ai5DEHnmcGYrvNCnL41RJbpMYH4kKuVxMA= +7ZQA9aC5XgjSZxYMRGcjU6RIPxwtbJSJmaeL0j6CfNs= diff --git a/tests/integration/message/message_count_cap/message_count_cap.0.hash b/tests/integration/message/message_count_cap/message_count_cap.0.hash index a383538a..9d6bda46 100644 --- a/tests/integration/message/message_count_cap/message_count_cap.0.hash +++ b/tests/integration/message/message_count_cap/message_count_cap.0.hash @@ -1 +1 @@ -3Vh9/mJaiAF31E208xGAiEELYPYg/brdniOHufg8+Ew= +cgV6MriNRvMOliPi4KpKel3gp23MMKvxUlT8t/tMaSo= diff --git a/tests/integration/message/message_count_cap/message_count_cap.1.hash b/tests/integration/message/message_count_cap/message_count_cap.1.hash index 97eefe70..5751168e 100644 --- a/tests/integration/message/message_count_cap/message_count_cap.1.hash +++ b/tests/integration/message/message_count_cap/message_count_cap.1.hash @@ -1 +1 @@ -KNwr/Dy0zCrcaJYvXzfr5+kbmlCNKBap09++Q8f9Qjo= +JCZf0dkn6FMj+cZbxlVM/V/KHXU4Bn2vZWH1vaxiUbM= diff --git a/tests/integration/message/message_count_cap/message_count_cap.2.hash b/tests/integration/message/message_count_cap/message_count_cap.2.hash index 5b3cfeba..41dd3e6d 100644 --- a/tests/integration/message/message_count_cap/message_count_cap.2.hash +++ b/tests/integration/message/message_count_cap/message_count_cap.2.hash @@ -1 +1 @@ -6ry9qm8Ix91BuIgwjLVN+i11PoWEcCnQB1EXSI0wT1s= +V3z/2NtS1TqsiuotFFvmVrUcRoveQFFt2qkLKXCjmb4= diff --git a/tests/integration/message/message_count_cap/message_count_cap.3.hash b/tests/integration/message/message_count_cap/message_count_cap.3.hash index 679f2125..1a4847de 100644 --- a/tests/integration/message/message_count_cap/message_count_cap.3.hash +++ b/tests/integration/message/message_count_cap/message_count_cap.3.hash @@ -1 +1 @@ -avr4cHakpGX9ecKiU+X8mT3htXgk850LxPLsnx+qR6U= +WPiHOOiVDIOo/W1SWFRkfxqKn5sxBemRZtFFzwrZ1oQ= diff --git a/tests/integration/message/message_count_cap/message_count_cap.4.hash b/tests/integration/message/message_count_cap/message_count_cap.4.hash index 0a9c27a7..ce99ba5f 100644 --- a/tests/integration/message/message_count_cap/message_count_cap.4.hash +++ b/tests/integration/message/message_count_cap/message_count_cap.4.hash @@ -1 +1 @@ -fVnNaBcVFyegjBROF457gNxlOSyJb/zxDbuQZt+2Ais= +Fo0uTPlEaH2fChxLQAuTz9Gh9JLm9EhEb6At/PnkQfM= diff --git a/tests/integration/message/message_count_cap/message_count_cap.5.hash b/tests/integration/message/message_count_cap/message_count_cap.5.hash index 55ba9132..52bac632 100644 --- a/tests/integration/message/message_count_cap/message_count_cap.5.hash +++ b/tests/integration/message/message_count_cap/message_count_cap.5.hash @@ -1 +1 @@ -lzOMq7BjovYc5aA7MWrGfFtM7AvQYL4HUvm2/cIMKKk= +8wS5WPtLODTbTkW6tTsPA3KKMykTeOwbY1RX0K+mjqg= diff --git a/tests/integration/message/method/methods.0.hash b/tests/integration/message/method/methods.0.hash index e95b3e8c..71977823 100644 --- a/tests/integration/message/method/methods.0.hash +++ b/tests/integration/message/method/methods.0.hash @@ -1 +1 @@ -UCb/xDwNFrOnLk3/vnHVBJ3v0CP2VzJrjXbnMeeqAKw= +5f4SOk5+WBjuEF6MDsYvpVFqg4IZXNwOabpOFh5JYkM= diff --git a/tests/integration/message/method/methods.0_0.hash b/tests/integration/message/method/methods.0_0.hash index 987bb653..9e842c86 100644 --- a/tests/integration/message/method/methods.0_0.hash +++ b/tests/integration/message/method/methods.0_0.hash @@ -1 +1 @@ -k1KMY+04tym+qqH63dRsY8okzWgG9EcefjF7c966RiA= +CuKV/MOXwbctwnBH4q3pBAPftYMIXEh9IWEdJwhkVZ0= diff --git a/tests/integration/message/method/methods.0_1.hash b/tests/integration/message/method/methods.0_1.hash index 542037af..4e22fbb9 100644 --- a/tests/integration/message/method/methods.0_1.hash +++ b/tests/integration/message/method/methods.0_1.hash @@ -1 +1 @@ -Lm3cbjWlg9Nae/hqC27IYpycySkIX/llPf96f4a5YOM= +z9yxSTy6v75Tg9NSKgwoKGnVVoDMkNIdcTAiWtyNjS8= diff --git a/tests/integration/message/method/methods.0_2.hash b/tests/integration/message/method/methods.0_2.hash index 7e1f0d55..b98775fe 100644 --- a/tests/integration/message/method/methods.0_2.hash +++ b/tests/integration/message/method/methods.0_2.hash @@ -1 +1 @@ -Pu4BNF3HYgpj3MwMtbRDHmsTCWYzZyEaZqlZudBn2Bo= +6vMFRYLbOiLukL6L6+9PJo6+Qa1i6l3lirYMPwHJbKw= diff --git a/tests/integration/message/method/methods.0_3.hash b/tests/integration/message/method/methods.0_3.hash index e2210b9c..bfc9278c 100644 --- a/tests/integration/message/method/methods.0_3.hash +++ b/tests/integration/message/method/methods.0_3.hash @@ -1 +1 @@ -XBYuPotf+y7Z9QFsrwJ3EG4MVX6aQaqjEgTzoCzy13o= +YH4fBTUiN/MJZsFUbWA9x2OZm/73UT7RS1I9ixGb1Co= diff --git a/tests/integration/message/nested_allocation_budget/nested_allocation_budget.0.hash b/tests/integration/message/nested_allocation_budget/nested_allocation_budget.0.hash index 3c007349..90591d71 100644 --- a/tests/integration/message/nested_allocation_budget/nested_allocation_budget.0.hash +++ b/tests/integration/message/nested_allocation_budget/nested_allocation_budget.0.hash @@ -1 +1 @@ -zFjD8qr23ZgJ8k18CpqAP7E8FtJolCDBRFJbKrzz4I0= +b1mqnS6xoVLRani60H3FnZBvV+bUeoQO7+lTSrTp+uM= diff --git a/tests/integration/message/send_message/send_message.0.hash b/tests/integration/message/send_message/send_message.0.hash index 59c6c936..af331975 100644 --- a/tests/integration/message/send_message/send_message.0.hash +++ b/tests/integration/message/send_message/send_message.0.hash @@ -1 +1 @@ -UQb2gkxE347cURyeM7Ncufg1kW0PmCK6LdnLAaBRF4w= +CVITn5bHzkKGttf1BE5fYey0dtw7TyPZa1vHzLDSdgg= diff --git a/tests/integration/message/send_message_eth/send_message_eth.0.hash b/tests/integration/message/send_message_eth/send_message_eth.0.hash index 4cf20bcc..ecaa5291 100644 --- a/tests/integration/message/send_message_eth/send_message_eth.0.hash +++ b/tests/integration/message/send_message_eth/send_message_eth.0.hash @@ -1 +1 @@ -rzZmEKvGd5nrrhobnlgBDxqi7FwdBGPnXHXp9cQ0gE8= +venfxmOi2jERTSZoL96bEGm/XMZkL3G9eJMQ753kRvQ= diff --git a/tests/integration/message/send_message_on/send_message_on.0.hash b/tests/integration/message/send_message_on/send_message_on.0.hash index 61546e40..dcd89018 100644 --- a/tests/integration/message/send_message_on/send_message_on.0.hash +++ b/tests/integration/message/send_message_on/send_message_on.0.hash @@ -1 +1 @@ -DY6NN56fz41U2PmXbvycCQEyKvFFjDgBz2JeqDLO5HA= +jgtGj4spU7hdLIkK/YmxscrWKso9aoC/lZqsNMgewic= diff --git a/tests/integration/message/send_message_on/send_message_on.0_0.hash b/tests/integration/message/send_message_on/send_message_on.0_0.hash index 8d3e7878..e80cb04b 100644 --- a/tests/integration/message/send_message_on/send_message_on.0_0.hash +++ b/tests/integration/message/send_message_on/send_message_on.0_0.hash @@ -1 +1 @@ -BG+CviBBbNBgbVzhKnkjhFVlh6WO2CJ6tcMC2M2HnF8= +xzF8lmdDwbvUFEdHOGtV1woH4tLATMNkDDvy5hurPvE= diff --git a/tests/integration/message/send_message_on/send_message_on.0_0_0.hash b/tests/integration/message/send_message_on/send_message_on.0_0_0.hash index 1f04bde9..8863d572 100644 --- a/tests/integration/message/send_message_on/send_message_on.0_0_0.hash +++ b/tests/integration/message/send_message_on/send_message_on.0_0_0.hash @@ -1 +1 @@ -SHeXyxm/f7UJB+cNUQwj7RpVjXbDCxgEP6KLVccU124= +Vwv8sGDkKyqUjVccucr4pRfx99XImNrdyWhnul4TGjU= diff --git a/tests/integration/message/undefined_all/undefined_all.0.hash b/tests/integration/message/undefined_all/undefined_all.0.hash index 34344031..4f793730 100644 --- a/tests/integration/message/undefined_all/undefined_all.0.hash +++ b/tests/integration/message/undefined_all/undefined_all.0.hash @@ -1 +1 @@ -HsYAwZdJcHZV9KiAwaTGIkTBNeQUaVLrO3xSDYFbLEc= +uebf5APgnFCus1Yqady5dVZBI27s5mdXjkJcDPXrxmk= diff --git a/tests/integration/message/undefined_all/undefined_all.0_0.hash b/tests/integration/message/undefined_all/undefined_all.0_0.hash index 38931e57..fa6ad2e1 100644 --- a/tests/integration/message/undefined_all/undefined_all.0_0.hash +++ b/tests/integration/message/undefined_all/undefined_all.0_0.hash @@ -1 +1 @@ -OwywO13ramfieyLZzaj/eCESHN1065fz5hLGUsK+578= +JYnFyLv3rvPrUZNXYQO6HpBmdofSt8ncEhEiIrwpvGY= diff --git a/tests/integration/message/undefined_all/undefined_all.0_0_0.hash b/tests/integration/message/undefined_all/undefined_all.0_0_0.hash index e12284cf..0465839a 100644 --- a/tests/integration/message/undefined_all/undefined_all.0_0_0.hash +++ b/tests/integration/message/undefined_all/undefined_all.0_0_0.hash @@ -1 +1 @@ -zQp3wNUTtmQ7T0QCfATVPFlDJL7RUhvVT8EIQgmKHcc= +ui/42VX1uiokwQQ29qxlsvu1Dga067BkI1zUWOdIPzY= diff --git a/tests/integration/message/undefined_method/undefined_method.0.hash b/tests/integration/message/undefined_method/undefined_method.0.hash index bba34619..49316315 100644 --- a/tests/integration/message/undefined_method/undefined_method.0.hash +++ b/tests/integration/message/undefined_method/undefined_method.0.hash @@ -1 +1 @@ -Dm/7WS3TXYpvOF7xl08PMq6t2W0F5zO5ziwZMjEbi9A= +rOqgHRaBVaW8SyKktvP8vlpl/cL0A74zgmUHNl7uBJ0= diff --git a/tests/integration/message/undefined_method/undefined_method.0_0.hash b/tests/integration/message/undefined_method/undefined_method.0_0.hash index c55428be..98ef0cc2 100644 --- a/tests/integration/message/undefined_method/undefined_method.0_0.hash +++ b/tests/integration/message/undefined_method/undefined_method.0_0.hash @@ -1 +1 @@ -RHV4UnD2L1iM9vP3Y3DbqdtBa/224qvL/82lXdHDIs4= +QsGJIZw821HfsTO7LGTPZVy4CY6PzdloSZkBC2TfXbo= diff --git a/tests/integration/message/undefined_method/undefined_method.0_0_0.hash b/tests/integration/message/undefined_method/undefined_method.0_0_0.hash index 4e95ce3f..7df43c64 100644 --- a/tests/integration/message/undefined_method/undefined_method.0_0_0.hash +++ b/tests/integration/message/undefined_method/undefined_method.0_0_0.hash @@ -1 +1 @@ -tMzz+ojMo+xgqOR4HlXBGsgiSBmhlJKTnG8InSSMq0I= +jlfjgVk3nFSz8rXqetLJjBwsfRqJFkgzG7dmPDkJsOc= diff --git a/tests/integration/message/undefined_method_payable/undefined_method_payable.0.hash b/tests/integration/message/undefined_method_payable/undefined_method_payable.0.hash index d5dbb7c9..03f81d18 100644 --- a/tests/integration/message/undefined_method_payable/undefined_method_payable.0.hash +++ b/tests/integration/message/undefined_method_payable/undefined_method_payable.0.hash @@ -1 +1 @@ -6FJFfBg5LE9Oq37kisq4N7WWg+V+YA/1AHV3vj8JCSw= +esg4ti2bd4M43wK+qCv1ahI2D+dHtgjqiBNlob6NJu8= diff --git a/tests/integration/message/undefined_method_payable/undefined_method_payable.0_0.hash b/tests/integration/message/undefined_method_payable/undefined_method_payable.0_0.hash index 25e9039f..b5168a51 100644 --- a/tests/integration/message/undefined_method_payable/undefined_method_payable.0_0.hash +++ b/tests/integration/message/undefined_method_payable/undefined_method_payable.0_0.hash @@ -1 +1 @@ -97jKCH8FbJBICmb81Mk5H7ADNq9B+fjfkndTiiAGbx4= +w7LANKYDFNFq0JSJPZgrK/6HqAE8xHli1V0aAGtuP2c= diff --git a/tests/integration/message/undefined_method_payable/undefined_method_payable.0_0_0.hash b/tests/integration/message/undefined_method_payable/undefined_method_payable.0_0_0.hash index 3c0147ec..ca70f952 100644 --- a/tests/integration/message/undefined_method_payable/undefined_method_payable.0_0_0.hash +++ b/tests/integration/message/undefined_method_payable/undefined_method_payable.0_0_0.hash @@ -1 +1 @@ -leIoBVDLYtShv5lsv4jr9dqeMzQHXuqFIeGunQk0dys= +SwD9KptrQjbhoQwJqymccl6dzH53ZopAWyAyehV1zoc= diff --git a/tests/integration/message/undefined_receive/undefined_receive.0.hash b/tests/integration/message/undefined_receive/undefined_receive.0.hash index 775ad2b3..edfc89e0 100644 --- a/tests/integration/message/undefined_receive/undefined_receive.0.hash +++ b/tests/integration/message/undefined_receive/undefined_receive.0.hash @@ -1 +1 @@ -de+hbZgPKwPduLHPsirfJCaC1nyLzcLAFT09a1XkafQ= +SPlhZg2Kd2njPxNKjEgeD7fIMRGzGUB+7H0ZzFKAF5M= diff --git a/tests/integration/message/undefined_receive/undefined_receive.0_0.hash b/tests/integration/message/undefined_receive/undefined_receive.0_0.hash index 62e2e01c..adec2599 100644 --- a/tests/integration/message/undefined_receive/undefined_receive.0_0.hash +++ b/tests/integration/message/undefined_receive/undefined_receive.0_0.hash @@ -1 +1 @@ -hJsSNQ+zeiN1kFA8m9CuCRFmVB6/i3X20Ueg1CAUAPY= +ANldNr/u65K+UejD6IoowCek4sKmVHDKqa82jn0j80I= diff --git a/tests/integration/message/undefined_receive/undefined_receive.0_0_0.hash b/tests/integration/message/undefined_receive/undefined_receive.0_0_0.hash index 6949d49c..ef2ff2cc 100644 --- a/tests/integration/message/undefined_receive/undefined_receive.0_0_0.hash +++ b/tests/integration/message/undefined_receive/undefined_receive.0_0_0.hash @@ -1 +1 @@ -iMzHfkx1p78ccTSRCA+2Ou3WlSEnXfQUZz2jwPItvLc= +VsVTnMZBNzVCv/H3qtifvzDZMz+HiFydRe0oifOt+Dg= diff --git a/tests/integration/message/unmatched_external_guard/unmatched_external_guard.closed.hash b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.closed.hash new file mode 100644 index 00000000..09753fb8 --- /dev/null +++ b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.closed.hash @@ -0,0 +1 @@ +C/2qJM7vYgX2fYUC+UQq7xoJgviikjhDaRV+JtOALdw= diff --git a/tests/integration/message/unmatched_external_guard/unmatched_external_guard.closed.stdout b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.closed.stdout new file mode 100644 index 00000000..f6b1ac19 --- /dev/null +++ b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.closed.stdout @@ -0,0 +1 @@ +executed with `VMError("out_of message_fee allocation_budget # external")` diff --git a/tests/integration/message/unmatched_external_guard/unmatched_external_guard.jsonnet b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.jsonnet new file mode 100644 index 00000000..6906377c --- /dev/null +++ b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.jsonnet @@ -0,0 +1,51 @@ +local simpleDeploy = import 'templates/simple_deploy.jsonnet'; +local util = import 'templates/util.jsonnet'; + +local guard = { + budget: 0, + recipient: null, + call_key: null, + on: 'finalized', + fee_params: { + External: { + gas_limit: 1, + max_gas_price: '115792089237316195423570985008687907853269984665640564039457584007913129639935', + }, + }, + children_budget: 0, + subtree: [], +}; + +local pinned = { + budget: 1000, + recipient: 'ERERERERERERERERERERERERERE=', + call_key: null, + on: 'finalized', + fee_params: { + External: { + gas_limit: 100, + max_gas_price: 1, + }, + }, + children_budget: 0, + subtree: [], +}; + +local run = simpleDeploy.run('${jsonnetDir}/${fileBaseName}.py'); +{ + tags: util.features([['message', 'send', 'eth'], ['fees']], 'stable') + ['python'], + entry: util.addPaths([ + run + { + slug: 'pinned', + message_fee_allocation: [pinned, guard], + }, + run + { + slug: 'closed', + message_fee_allocation: [guard], + }, + run + { + slug: 'no_allocations', + message_fee_allocation: [], + }, + ]), +} diff --git a/tests/integration/message/unmatched_external_guard/unmatched_external_guard.no_allocations.hash b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.no_allocations.hash new file mode 100644 index 00000000..be144851 --- /dev/null +++ b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.no_allocations.hash @@ -0,0 +1 @@ +rQalwUnnh+varU3qXfSDgDApd3jsIpqgVzznKkFpo5g= diff --git a/tests/integration/message/unmatched_external_guard/unmatched_external_guard.no_allocations.stdout b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.no_allocations.stdout new file mode 100644 index 00000000..8e100e59 --- /dev/null +++ b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.no_allocations.stdout @@ -0,0 +1,2 @@ +executed with `Return(null)` +{"address":addr#3030303030303030303030303030303030303030,"calldata":b#2b0969260000000000000000000000000000000000000000000000000000000000000001,"fee_params":{"gas_limit":0,"max_gas_price":0},"message_fee":0,"receipt_fee":737,"type":"ExternalMessage","value":0} diff --git a/tests/integration/message/unmatched_external_guard/unmatched_external_guard.pinned.hash b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.pinned.hash new file mode 100644 index 00000000..09753fb8 --- /dev/null +++ b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.pinned.hash @@ -0,0 +1 @@ +C/2qJM7vYgX2fYUC+UQq7xoJgviikjhDaRV+JtOALdw= diff --git a/tests/integration/message/unmatched_external_guard/unmatched_external_guard.pinned.stdout b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.pinned.stdout new file mode 100644 index 00000000..f6b1ac19 --- /dev/null +++ b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.pinned.stdout @@ -0,0 +1 @@ +executed with `VMError("out_of message_fee allocation_budget # external")` diff --git a/tests/integration/message/unmatched_external_guard/unmatched_external_guard.py b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.py new file mode 100644 index 00000000..f3eb9e6f --- /dev/null +++ b/tests/integration/message/unmatched_external_guard/unmatched_external_guard.py @@ -0,0 +1,17 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.types import Address, u256 + + +@gl.evm.contract_interface +class ExternalTarget: + class View: + pass + + class Write: + def call(self, value: u256, /) -> None: ... + + +class Contract(gl.contract.Contract): + def __init__(self): + ExternalTarget(Address(b'\x30' * 20)).emit().call(1) diff --git a/tests/integration/message/use_balance_below_min/use_balance_below_min.0.hash b/tests/integration/message/use_balance_below_min/use_balance_below_min.0.hash index 980e4b52..3bca016e 100644 --- a/tests/integration/message/use_balance_below_min/use_balance_below_min.0.hash +++ b/tests/integration/message/use_balance_below_min/use_balance_below_min.0.hash @@ -1 +1 @@ -9niTt7fMets/o6Ak1GUlVKww6rvpWRt8X8uhxDovT2c= +a8UaEPCojq2sslelQ+ciFF3gj2jX9Nu+sEng1QZi9Xw= diff --git a/tests/integration/message/use_balance_below_min/use_balance_below_min.0_0.hash b/tests/integration/message/use_balance_below_min/use_balance_below_min.0_0.hash index 1faf3957..9f10f73b 100644 --- a/tests/integration/message/use_balance_below_min/use_balance_below_min.0_0.hash +++ b/tests/integration/message/use_balance_below_min/use_balance_below_min.0_0.hash @@ -1 +1 @@ -BvHNxhZIrWmAxZS6OW85R0eF64KPhFp8KgkOKvhJxI8= +K7WKe7tD+B1AxtFu1WseMwMCANYPOQxDjCcIbjwg758= diff --git a/tests/integration/message/use_balance_below_min/use_balance_below_min.py b/tests/integration/message/use_balance_below_min/use_balance_below_min.py index 8d25d5a4..e87eddbb 100644 --- a/tests/integration/message/use_balance_below_min/use_balance_below_min.py +++ b/tests/integration/message/use_balance_below_min/use_balance_below_min.py @@ -25,5 +25,5 @@ def __init__(self): def do_emit(self): # Phase bounds are enforced on the balance-funded path too. gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) diff --git a/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.0.hash b/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.0.hash index a0e7d9cb..eb5f34ad 100644 --- a/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.0.hash +++ b/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.0.hash @@ -1 +1 @@ -C/xgKD7rxWsi0fm8gg8HJ4D4Q3KUURZMrO7SRhkRwyE= +Lmd58zBnHhUYvbdggU1Igs1trhsGwysAxjWKboZTQCg= diff --git a/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.0_0.hash b/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.0_0.hash index 5204972f..043240aa 100644 --- a/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.0_0.hash +++ b/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.0_0.hash @@ -1 +1 @@ -m6g/ESaYxM2iqW+WiT99Z5cy83ye+MPFGDjByp7W0rI= +ij3x4frDwtVAnHK7jD9TBvJLjq6W8bbwwPTuoH306Gw= diff --git a/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.py b/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.py index 9e3d7ed3..cfa2535a 100644 --- a/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.py +++ b/tests/integration/message/use_balance_budget_too_low/use_balance_budget_too_low.py @@ -26,5 +26,5 @@ def __init__(self): def do_emit(self): # Metering aborts with the `fee below_minimum` VMError (budget floor). gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.0.stdout b/tests/integration/message/use_balance_descendants/use_balance_descendants.0.stdout new file mode 100644 index 00000000..7d73027c --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.0.stdout @@ -0,0 +1 @@ +executed with `Return(null)` diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.0_closed_zero.stdout b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_closed_zero.stdout new file mode 100644 index 00000000..db6d0469 --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_closed_zero.stdout @@ -0,0 +1,2 @@ +executed with `Return(null)` +{"address":addr#3030303030303030303030303030303030303030,"call_key":b#666f6f0000000000000000000000000000000000000000000000000000000000,"calldata":{"":"foo"},"fee_params":{"execution_budget_per_round":1024,"leader_timeunits_allocation":5,"max_price_gen_per_time_unit":2,"receipt_fee_max_gas_price":20,"rotations":[4,4,4,4,4],"storage_fee_max_gas_price":20,"validator_timeunits_allocation":5},"message_fee":53476,"on":"finalized","receipt_fee":1121,"subtree":b#,"type":"InternalMessage","use_balance":true,"value":0} diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.0_deploy_open.stdout b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_deploy_open.stdout new file mode 100644 index 00000000..c37a2a2a --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_deploy_open.stdout @@ -0,0 +1,2 @@ +executed with `Return(null)` +{"calldata":{},"code":b#,"fee_params":{"execution_budget_per_round":1024,"leader_timeunits_allocation":5,"max_price_gen_per_time_unit":2,"receipt_fee_max_gas_price":20,"rotations":[4,4,4,4,4],"storage_fee_max_gas_price":20,"validator_timeunits_allocation":5},"message_fee":353476,"on":"finalized","receipt_fee":1409,"salt_nonce":0,"subtree":b#5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000493e000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000,"type":"InternalDeployMessage","use_balance":true,"value":0} diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.0_duplicate_external_selector.stdout b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_duplicate_external_selector.stdout new file mode 100644 index 00000000..29570012 --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_duplicate_external_selector.stdout @@ -0,0 +1 @@ +executed with `VMError("fee descendant_grant tree")` diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.0_external_budget.stdout b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_external_budget.stdout new file mode 100644 index 00000000..4b9bb263 --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_external_budget.stdout @@ -0,0 +1 @@ +executed with `VMError("fee descendant_grant external")` diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.0_invalid_tree.stdout b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_invalid_tree.stdout new file mode 100644 index 00000000..29570012 --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_invalid_tree.stdout @@ -0,0 +1 @@ +executed with `VMError("fee descendant_grant tree")` diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.0_nested_decided_underfunded.stdout b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_nested_decided_underfunded.stdout new file mode 100644 index 00000000..dd9a7bda --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_nested_decided_underfunded.stdout @@ -0,0 +1 @@ +executed with `VMError("fee descendant_grant budget")` diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.0_open.stdout b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_open.stdout new file mode 100644 index 00000000..6568441c --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_open.stdout @@ -0,0 +1,2 @@ +executed with `Return(null)` +{"address":addr#3030303030303030303030303030303030303030,"call_key":b#666f6f0000000000000000000000000000000000000000000000000000000000,"calldata":{"":"foo"},"fee_params":{"execution_budget_per_round":1024,"leader_timeunits_allocation":5,"max_price_gen_per_time_unit":2,"receipt_fee_max_gas_price":20,"rotations":[4,4,4,4,4],"storage_fee_max_gas_price":20,"validator_timeunits_allocation":5},"message_fee":353476,"on":"finalized","receipt_fee":1345,"subtree":b#5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000493e000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000,"type":"InternalMessage","use_balance":true,"value":0} diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.0_pinned_nested.stdout b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_pinned_nested.stdout new file mode 100644 index 00000000..7d4d830e --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_pinned_nested.stdout @@ -0,0 +1,2 @@ +executed with `Return(null)` +{"address":addr#3030303030303030303030303030303030303030,"call_key":b#666f6f0000000000000000000000000000000000000000000000000000000000,"calldata":{"":"foo"},"fee_params":{"execution_budget_per_round":1024,"leader_timeunits_allocation":5,"max_price_gen_per_time_unit":2,"receipt_fee_max_gas_price":20,"rotations":[4,4,4,4,4],"storage_fee_max_gas_price":20,"validator_timeunits_allocation":5},"message_fee":453676,"on":"finalized","receipt_fee":3233,"subtree":b#5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000061b480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061a8000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041eb000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000003333333333333333333333333333333333333333c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47000000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000a,"type":"InternalMessage","use_balance":true,"value":0} diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.0_pinned_selector.stdout b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_pinned_selector.stdout new file mode 100644 index 00000000..6da4e89e --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.0_pinned_selector.stdout @@ -0,0 +1,2 @@ +executed with `Return(null)` +{"address":addr#3030303030303030303030303030303030303030,"call_key":b#666f6f0000000000000000000000000000000000000000000000000000000000,"calldata":{"":"foo"},"fee_params":{"execution_budget_per_round":1024,"leader_timeunits_allocation":5,"max_price_gen_per_time_unit":2,"receipt_fee_max_gas_price":20,"rotations":[4,4,4,4,4],"storage_fee_max_gas_price":20,"validator_timeunits_allocation":5},"message_fee":453676,"on":"finalized","receipt_fee":3233,"subtree":b#5f77181a28fb88dd0597390f852a7f174bad95303defeefb5ba806aaa3ef64fb0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000061b480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061a8000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041eb000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000003333333333333333333333333333333333333333a9059cbb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000a,"type":"InternalMessage","use_balance":true,"value":0} diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.jsonnet b/tests/integration/message/use_balance_descendants/use_balance_descendants.jsonnet new file mode 100644 index 00000000..2011f374 --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.jsonnet @@ -0,0 +1,33 @@ +local deployThen = import 'templates/simple_deploy_then_write.jsonnet'; +local util = import 'templates/util.jsonnet'; + +local balance = { + balances: { + 'AQAAAAAAAAAAAAAAAAAAAAAAAAA=': 10000000, + }, +}; +local base = deployThen.run('${jsonnetDir}/${fileBaseName}.py', 'open'); +local write(method) = base.next[0] + balance + { + slug: method, + calldata: std.manifestJsonEx({'': method}, ' '), +}; +local case = base + balance + { + next: [ + write('open'), + write('closed_zero'), + write('pinned_nested'), + write('invalid_tree'), + write('external_budget'), + write('deploy_open'), + write('nested_decided_underfunded'), + write('duplicate_external_selector'), + write('pinned_selector'), + ], +}; +{ + tags: util.features( + [['message', 'send'], ['balance'], ['fees', 'balance']], + 'stable' + ) + ['python'], + entry: util.addPaths(util.mapGraph(function(entry) entry + {stable_hash: false}, [case])), +} diff --git a/tests/integration/message/use_balance_descendants/use_balance_descendants.py b/tests/integration/message/use_balance_descendants/use_balance_descendants.py new file mode 100644 index 00000000..abd326c1 --- /dev/null +++ b/tests/integration/message/use_balance_descendants/use_balance_descendants.py @@ -0,0 +1,140 @@ +# { "Depends": "py-genlayer:test" } +import genlayer as gl +from genlayer.vm.public_abi import Permissions + +_PARAMS = gl.chain.InternalMessageParams( + leader_time_units_allocation=5, + validator_time_units_allocation=5, + execution_budget_per_round=1024, + rotations=[4, 4, 4, 4, 4], + max_price_gen_per_time_unit=2, + storage_fee_max_gas_price=20, + receipt_fee_max_gas_price=20, +) +_TARGET = gl.contract.get_at(gl.Address(b'\x30' * 20)) + + +class Contract(gl.contract.Contract): + def __init__(self): + gl.storage.Root.get().set_permission( + Permissions.CAN_USE_BALANCE_FOR_MESSAGE_FEES, True + ) + + @gl.public.write + def open(self): + _TARGET.emit( + use_balance=gl.contract.UseBalanceParams(_PARAMS, descendants=300_000) + ).foo() + + @gl.public.write + def closed_zero(self): + _TARGET.emit(use_balance=gl.contract.UseBalanceParams(_PARAMS, descendants=0)).foo() + + @gl.public.write + def pinned_nested(self): + self._emit_pinned(None) + + @gl.public.write + def pinned_selector(self): + self._emit_pinned(bytes.fromhex('a9059cbb')) + + def _emit_pinned(self, external_call_key): + root = gl.message_allocation.InternalAllocation( + gl.Address(b'\x11' * 20), + bytes(32), + _PARAMS, + 400_000, + children=[ + gl.message_allocation.InternalAllocation( + gl.Address(b'\x22' * 20), + bytes(32), + _PARAMS, + 270_000, + on='decided', + ) + ], + ) + external = gl.message_allocation.ExternalAllocation( + gl.Address(b'\x33' * 20), + external_call_key, + gl.chain.ExternalMessageParams(20, 10), + 200, + ) + _TARGET.emit( + use_balance=gl.contract.UseBalanceParams(_PARAMS, descendants=[root, external]), + ).foo() + + @gl.public.write + def invalid_tree(self): + root = gl.message_allocation.InternalAllocation( + gl.Address(b'\x11' * 20), None, _PARAMS, 60_000 + ) + duplicate = gl.message_allocation.InternalAllocation( + gl.Address(b'\x11' * 20), + gl.message_allocation.ANY_METHOD, + _PARAMS, + 300_000, + on='decided', + ) + _TARGET.emit( + use_balance=gl.contract.UseBalanceParams(_PARAMS, descendants=[root, duplicate]), + ).foo() + + @gl.public.write + def external_budget(self): + external = gl.message_allocation.ExternalAllocation( + gl.Address(b'\x33' * 20), + bytes.fromhex('a9059cbb'), + gl.chain.ExternalMessageParams(20, 10), + 199, + ) + _TARGET.emit( + use_balance=gl.contract.UseBalanceParams(_PARAMS, descendants=[external]), + ).foo() + + @gl.public.write + def duplicate_external_selector(self): + selector = bytes.fromhex('a9059cbb') + nodes: list[ + gl.message_allocation.InternalAllocation + | gl.message_allocation.ExternalAllocation + ] = [ + gl.message_allocation.ExternalAllocation( + gl.Address(b'\x33' * 20), + key, + gl.chain.ExternalMessageParams(20, 10), + 200, + ) + for key in (selector, selector + bytes(28)) + ] + _TARGET.emit( + use_balance=gl.contract.UseBalanceParams(_PARAMS, descendants=nodes) + ).foo() + + @gl.public.write + def deploy_open(self): + gl.contract.deploy( + code=b'', + use_balance=gl.contract.UseBalanceParams(_PARAMS, descendants=300_000), + ) + + @gl.public.write + def nested_decided_underfunded(self): + root = gl.message_allocation.InternalAllocation( + gl.Address(b'\x11' * 20), + bytes(32), + _PARAMS, + 400_000, + children=[ + gl.message_allocation.InternalAllocation( + gl.Address(b'\x22' * 20), + bytes(32), + _PARAMS, + 267_379, + on='decided', + ) + ], + ) + _TARGET.emit( + use_balance=gl.contract.UseBalanceParams(_PARAMS, descendants=[root]), + ).foo() diff --git a/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.0.hash b/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.0.hash index 844aae20..3fe3e765 100644 --- a/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.0.hash +++ b/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.0.hash @@ -1 +1 @@ -1r4itiWgvP2P6TtOQw9YvMmoBvrW9N13JXoSQ13Rqe4= +iH/HQk9EDaKhU4V6RiZLOqRgCIM0+JO7e5IY0ou64zI= diff --git a/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.0_0.hash b/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.0_0.hash index da6950a7..860a100e 100644 --- a/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.0_0.hash +++ b/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.0_0.hash @@ -1 +1 @@ -hgrVavfcXAG6St/KMewZ/5FBNoO7/pDUSz47Yt+cMuI= +rYcFQYJSMpcGGmhPxYUFn6T4ZiODbQo5OGcs3di+NxQ= diff --git a/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.py b/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.py index f91cbd7b..350e734a 100644 --- a/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.py +++ b/tests/integration/message/use_balance_empty_rotations/use_balance_empty_rotations.py @@ -27,7 +27,7 @@ def do_emit(self): # use_balance with empty rotations is rejected with Inval (errno 2). try: gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) except SystemError as e: print(e) diff --git a/tests/integration/message/use_balance_forbidden/use_balance_forbidden.0.hash b/tests/integration/message/use_balance_forbidden/use_balance_forbidden.0.hash index 19e0f332..d18ce665 100644 --- a/tests/integration/message/use_balance_forbidden/use_balance_forbidden.0.hash +++ b/tests/integration/message/use_balance_forbidden/use_balance_forbidden.0.hash @@ -1 +1 @@ -gcFQnYB5FTDBW/godQYNmrSWYo+h/EqxkSS9iBUSk8I= +67vepMHM80rSzA1oRc3JrocJYEdnfRjNBZcijFPhEJA= diff --git a/tests/integration/message/use_balance_forbidden/use_balance_forbidden.0_0.hash b/tests/integration/message/use_balance_forbidden/use_balance_forbidden.0_0.hash index 1a51b321..88ee158f 100644 --- a/tests/integration/message/use_balance_forbidden/use_balance_forbidden.0_0.hash +++ b/tests/integration/message/use_balance_forbidden/use_balance_forbidden.0_0.hash @@ -1 +1 @@ -kNRk1iYGHH5eAhMvNQfZRJN1D5vRkS0Pnphfbqmkzqo= +ldJgElEGhiQZudzhylzQNI9G13O79ohzC8LBkajZczA= diff --git a/tests/integration/message/use_balance_forbidden/use_balance_forbidden.py b/tests/integration/message/use_balance_forbidden/use_balance_forbidden.py index 41c8f23c..cc7f0e4f 100644 --- a/tests/integration/message/use_balance_forbidden/use_balance_forbidden.py +++ b/tests/integration/message/use_balance_forbidden/use_balance_forbidden.py @@ -25,7 +25,7 @@ def do_emit(self): # so the result stays `Return`. try: gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) except SystemError as e: print(e) diff --git a/tests/integration/message/use_balance_huge_params/use_balance_huge_params.0.hash b/tests/integration/message/use_balance_huge_params/use_balance_huge_params.0.hash index 8a47f2f8..3a1644ac 100644 --- a/tests/integration/message/use_balance_huge_params/use_balance_huge_params.0.hash +++ b/tests/integration/message/use_balance_huge_params/use_balance_huge_params.0.hash @@ -1 +1 @@ -bsxA8OdfCh0iqJMUQO4+7EVuom1bwMxM848zoL5+xfQ= +Iv6Nki4sDaNcBddkx/0z+8ESDJXo5hfI4OBB7POLYgE= diff --git a/tests/integration/message/use_balance_huge_params/use_balance_huge_params.0_0.hash b/tests/integration/message/use_balance_huge_params/use_balance_huge_params.0_0.hash index f09a7fae..45fcf42a 100644 --- a/tests/integration/message/use_balance_huge_params/use_balance_huge_params.0_0.hash +++ b/tests/integration/message/use_balance_huge_params/use_balance_huge_params.0_0.hash @@ -1 +1 @@ -zRlHu2uTJ/ql8d0Stb5Pqpuz3n2qBavraBGpFsT1VYM= +uxwM7na7O2wB2h+/NEEkjbgSL+QTFHn7DB1hgdwgt/8= diff --git a/tests/integration/message/use_balance_huge_params/use_balance_huge_params.py b/tests/integration/message/use_balance_huge_params/use_balance_huge_params.py index c864becf..65a1a2fd 100644 --- a/tests/integration/message/use_balance_huge_params/use_balance_huge_params.py +++ b/tests/integration/message/use_balance_huge_params/use_balance_huge_params.py @@ -8,7 +8,7 @@ # units, rotations entries) to < 2^32. _PARAMS = gl.chain.InternalMessageParams( leader_time_units_allocation=2**250, - validator_time_units_allocation=0, + validator_time_units_allocation=1, execution_budget_per_round=0, rotations=[0], max_price_gen_per_time_unit=2**250, @@ -29,7 +29,7 @@ def do_emit(self): # (errno 2), not an internal abort. try: gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) except SystemError as e: print(e) diff --git a/tests/integration/message/use_balance_insufficient/use_balance_insufficient.0.hash b/tests/integration/message/use_balance_insufficient/use_balance_insufficient.0.hash index e4592302..ea814889 100644 --- a/tests/integration/message/use_balance_insufficient/use_balance_insufficient.0.hash +++ b/tests/integration/message/use_balance_insufficient/use_balance_insufficient.0.hash @@ -1 +1 @@ -/tuZySTj4PeBdczHIu/RnHQhjFafv8jbPcavmQgWorY= +ibVW0E2Au/7yBbYLyAaTlsrcy0fUna5XaXqhKj4veqs= diff --git a/tests/integration/message/use_balance_insufficient/use_balance_insufficient.0_0.hash b/tests/integration/message/use_balance_insufficient/use_balance_insufficient.0_0.hash index b4bf6d6f..f6847dca 100644 --- a/tests/integration/message/use_balance_insufficient/use_balance_insufficient.0_0.hash +++ b/tests/integration/message/use_balance_insufficient/use_balance_insufficient.0_0.hash @@ -1 +1 @@ -EKdXChGj4ycMJ0uAfjayqAgJhxJqhfEcjULTf4HxdtU= +t8AWilSXLUgAudKV2DqfkQCyRPnfZXWP17tvuBg8DRk= diff --git a/tests/integration/message/use_balance_insufficient/use_balance_insufficient.py b/tests/integration/message/use_balance_insufficient/use_balance_insufficient.py index dcc8f858..5cb78931 100644 --- a/tests/integration/message/use_balance_insufficient/use_balance_insufficient.py +++ b/tests/integration/message/use_balance_insufficient/use_balance_insufficient.py @@ -26,7 +26,7 @@ def do_emit(self): # the guest just like a value overspend. try: gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) except SystemError as e: print(e) diff --git a/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0.hash b/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0.hash index 11154610..ec9dec5d 100644 --- a/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0.hash +++ b/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0.hash @@ -1 +1 @@ -hQTZnaHYFytJHUGsQKbk7rT8ChSwMyoJJrBr6ynma24= +2u8vmBvIdwwNZKJ84y4juREhz4TUdgAuqOABkAUgpz4= diff --git a/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0_0.hash b/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0_0.hash index 551e28f6..2dbb1a3f 100644 --- a/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0_0.hash +++ b/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0_0.hash @@ -1 +1 @@ -0HbG0DvGFXV3V93P78WUsPaASjBoejLLuPz75/URfE4= +SoXey0vKyw9opLXpMEIXuPpi0RuULILuRq2w6pF8+0o= diff --git a/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0_0_0.hash b/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0_0_0.hash index 3a6d12cc..a75bcd16 100644 --- a/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0_0_0.hash +++ b/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.0_0_0.hash @@ -1 +1 @@ -zn3+m8sYBCqoNT7la/O+Nnvdr8Gn3xnmBzURvphlUmA= +Gagt0JojQWITDF/tg+6Kd6/+KS/OZfpUFZxwBDhIZ1M= diff --git a/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.py b/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.py index 8d3d3e5f..403a41f9 100644 --- a/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.py +++ b/tests/integration/message/use_balance_no_alloc/use_balance_no_alloc.py @@ -33,5 +33,5 @@ def emit_balance(self): # use_balance bypasses allocation matching entirely, so the same # emission succeeds despite the empty tree. gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) diff --git a/tests/integration/message/use_balance_no_params/use_balance_no_params.0.hash b/tests/integration/message/use_balance_no_params/use_balance_no_params.0.hash index 5e3b0cfb..5bf8f0e0 100644 --- a/tests/integration/message/use_balance_no_params/use_balance_no_params.0.hash +++ b/tests/integration/message/use_balance_no_params/use_balance_no_params.0.hash @@ -1 +1 @@ -Ax5c5NfrLWkL9FRoyW6K0TAOltH3St4GyDaTKibA4cI= +ZPv0MdayrLpvnIa0Z/kl5fhczavJVHD2SVsj/z5cFiM= diff --git a/tests/integration/message/use_balance_no_params/use_balance_no_params.0_0.hash b/tests/integration/message/use_balance_no_params/use_balance_no_params.0_0.hash index a193d8b2..e8747c95 100644 --- a/tests/integration/message/use_balance_no_params/use_balance_no_params.0_0.hash +++ b/tests/integration/message/use_balance_no_params/use_balance_no_params.0_0.hash @@ -1 +1 @@ -Gw/4TiKSGc2oT9XEmYhMEwhmSHQnkMum4DXpo80y8o0= +Csqgx5lP/13IyX+35kK2KxM68G1Zu27jIWBQva7zsyU= diff --git a/tests/integration/message/use_balance_no_params/use_balance_no_params.py b/tests/integration/message/use_balance_no_params/use_balance_no_params.py index 890c290d..bcc37d34 100644 --- a/tests/integration/message/use_balance_no_params/use_balance_no_params.py +++ b/tests/integration/message/use_balance_no_params/use_balance_no_params.py @@ -16,6 +16,18 @@ def do_emit(self): # use_balance without fee_params is rejected with Inval (errno 2): # GenVM cannot meter the balance-funded fee without explicit params. try: - gl.contract.get_at(gl.Address(b'\x30' * 20)).emit(use_balance=True).foo(1, 2) + gl.wasi.gl_call( + gl.calldata.encode( + { + 'EmitInternalMessage': { + 'address': gl.Address(b'\x30' * 20), + 'calldata': {'': 'foo', 'args': [1, 2]}, + 'value': 0, + 'on': 'finalized', + 'use_balance': True, + } + } + ) + ) except SystemError as e: print(e) diff --git a/tests/integration/message/use_balance_ok/use_balance_ok.0.hash b/tests/integration/message/use_balance_ok/use_balance_ok.0.hash index 2dc22062..659373c4 100644 --- a/tests/integration/message/use_balance_ok/use_balance_ok.0.hash +++ b/tests/integration/message/use_balance_ok/use_balance_ok.0.hash @@ -1 +1 @@ -QSDsXWKaoyauzztpaZro/QuGj7jqNUolzpjDfBqwLt8= +G54rHxN2J1XxwLY628tlFL4xq7VXiRdLThrxsmMVhUQ= diff --git a/tests/integration/message/use_balance_ok/use_balance_ok.0_0.hash b/tests/integration/message/use_balance_ok/use_balance_ok.0_0.hash index 4bb6f2db..77382ded 100644 --- a/tests/integration/message/use_balance_ok/use_balance_ok.0_0.hash +++ b/tests/integration/message/use_balance_ok/use_balance_ok.0_0.hash @@ -1 +1 @@ -v+/q0enIeQ2YjL2n06ttkx6AvXFy1G1aH8OD3/svVL8= +ogMG3r0kL1oczqIibq8K3bY2sBflipV7qokRrurrGcE= diff --git a/tests/integration/message/use_balance_ok/use_balance_ok.py b/tests/integration/message/use_balance_ok/use_balance_ok.py index 2579260b..06036076 100644 --- a/tests/integration/message/use_balance_ok/use_balance_ok.py +++ b/tests/integration/message/use_balance_ok/use_balance_ok.py @@ -29,5 +29,5 @@ def do_emit(self): # succeeds. The metered fee is charged against this contract's balance # and the emitted message carries `use_balance=true` with an empty subtree. gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) diff --git a/tests/integration/message/use_balance_on_deploy/use_balance_on_deploy.0.hash b/tests/integration/message/use_balance_on_deploy/use_balance_on_deploy.0.hash index 63a5a417..1df3f954 100644 --- a/tests/integration/message/use_balance_on_deploy/use_balance_on_deploy.0.hash +++ b/tests/integration/message/use_balance_on_deploy/use_balance_on_deploy.0.hash @@ -1 +1 @@ -1bSpW7zr54WnkVX6maOUOWxMr7aMjfunEslACwkXUMY= +QG+nbmfoh66BXI4zrSbY6micdv+/tQ6qjilMVijPddc= diff --git a/tests/integration/message/use_balance_on_deploy/use_balance_on_deploy.py b/tests/integration/message/use_balance_on_deploy/use_balance_on_deploy.py index 49c1a109..7d634cf1 100644 --- a/tests/integration/message/use_balance_on_deploy/use_balance_on_deploy.py +++ b/tests/integration/message/use_balance_on_deploy/use_balance_on_deploy.py @@ -17,5 +17,5 @@ def __init__(self): # A deploy has no stored permission bitfield to read yet, so it runs with # every contract-owned permission granted: the emission must succeed. gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) diff --git a/tests/integration/message/use_balance_sandbox/use_balance_sandbox.0.hash b/tests/integration/message/use_balance_sandbox/use_balance_sandbox.0.hash index ac01d99b..0597d4d2 100644 --- a/tests/integration/message/use_balance_sandbox/use_balance_sandbox.0.hash +++ b/tests/integration/message/use_balance_sandbox/use_balance_sandbox.0.hash @@ -1 +1 @@ -kt3lwM3C41mG9i6h9q/8pXjD7SLIwVLxFZelqXuKcxg= +d0XuuUUy+mv3Q/KCVVXxAuD0IfNZsJqlTke30aJ+KuQ= diff --git a/tests/integration/message/use_balance_sandbox/use_balance_sandbox.0_0.hash b/tests/integration/message/use_balance_sandbox/use_balance_sandbox.0_0.hash index fa88911f..ba92a681 100644 --- a/tests/integration/message/use_balance_sandbox/use_balance_sandbox.0_0.hash +++ b/tests/integration/message/use_balance_sandbox/use_balance_sandbox.0_0.hash @@ -1 +1 @@ -4mGuHGPZtkSgBLtEizZjl6WIooJgNsf6iinL/NXQ4TI= +rsH2ZN9IC9gzWU1H/0BVLxhl8n00TSV3OtTO34BcL/4= diff --git a/tests/integration/message/use_balance_sandbox/use_balance_sandbox.py b/tests/integration/message/use_balance_sandbox/use_balance_sandbox.py index a968760d..5479ff78 100644 --- a/tests/integration/message/use_balance_sandbox/use_balance_sandbox.py +++ b/tests/integration/message/use_balance_sandbox/use_balance_sandbox.py @@ -30,7 +30,7 @@ def do_emit(self): def sandbox_fn(): try: gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) print('sandbox: emitted') except SystemError as e: diff --git a/tests/integration/message/use_balance_scaled/use_balance_scaled.0.hash b/tests/integration/message/use_balance_scaled/use_balance_scaled.0.hash index 0a68e692..b491dee1 100644 --- a/tests/integration/message/use_balance_scaled/use_balance_scaled.0.hash +++ b/tests/integration/message/use_balance_scaled/use_balance_scaled.0.hash @@ -1 +1 @@ -zA3XX1UxUJiJCIx/F5K9Onxx/zSX13VVFm6eLEps3WY= +atZ63AcZbhHOEgiEaxtOYSPHOxfP/DcXEzoIQNu+iFM= diff --git a/tests/integration/message/use_balance_scaled/use_balance_scaled.0_0.hash b/tests/integration/message/use_balance_scaled/use_balance_scaled.0_0.hash index 5eb382e6..40fab4b5 100644 --- a/tests/integration/message/use_balance_scaled/use_balance_scaled.0_0.hash +++ b/tests/integration/message/use_balance_scaled/use_balance_scaled.0_0.hash @@ -1 +1 @@ -cMf96TlPl5fPcvzq5Ik3iKwM+EAPd9Y3ZDA7Uf6ASPs= +6tHLnk1d1eRNDOO2Di/CbyZz3IUklkkCqp8qEnul1Rg= diff --git a/tests/integration/message/use_balance_scaled/use_balance_scaled.py b/tests/integration/message/use_balance_scaled/use_balance_scaled.py index bacbc208..25e0f33f 100644 --- a/tests/integration/message/use_balance_scaled/use_balance_scaled.py +++ b/tests/integration/message/use_balance_scaled/use_balance_scaled.py @@ -27,5 +27,5 @@ def __init__(self): @gl.public.write def do_emit(self): gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - on='decided', use_balance=True, fee_params=_PARAMS + on='decided', use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) diff --git a/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.0.hash b/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.0.hash index 28e903af..3383f744 100644 --- a/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.0.hash +++ b/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.0.hash @@ -1 +1 @@ -UJTGY/1qKNzr93VdDXPiAx9JMBi2HzazvW0Ke0geCn8= +9qf91dcRKsumz/2tKa6bHPbrRqW7picp/AXUu7yepQM= diff --git a/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.0_0.hash b/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.0_0.hash index bb20f570..d30391c3 100644 --- a/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.0_0.hash +++ b/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.0_0.hash @@ -1 +1 @@ -INfj7pDltiYxccr6vD8YZp+Zy8vsx0bK23vtNp0GhPs= +mvZRP1PcLxVx4OZF/RPcxb7Fz/nQtZJYfQ4peMhU3QE= diff --git a/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.py b/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.py index 691fdbd3..05db75e1 100644 --- a/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.py +++ b/tests/integration/message/use_balance_too_many_rounds/use_balance_too_many_rounds.py @@ -27,5 +27,5 @@ def __init__(self): def do_emit(self): # Metering aborts with `fee too_many_rounds`. gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) diff --git a/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.0.hash b/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.0.hash index 688c0929..8f943e82 100644 --- a/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.0.hash +++ b/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.0.hash @@ -1 +1 @@ -ppdtp9RoX+R8SIVzhCLFlRHWvWNZjzBt684AvyBrBNk= +xUwyjS2/46GwLHQx6qTpG3LuZKPZBcMWkg7kxdp07Fo= diff --git a/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.0_0.hash b/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.0_0.hash index e0cbd1f8..2d34fc6d 100644 --- a/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.0_0.hash +++ b/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.0_0.hash @@ -1 +1 @@ -iGXzkVvgCFfkv5eaIVnDKNZwIkLshmngSJRc43r26rI= ++8HfsldsFK6dlV9YqPATccH5PbLE9O5eRMAOzyOjuT0= diff --git a/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.py b/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.py index 35b90386..f35a5a29 100644 --- a/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.py +++ b/tests/integration/message/use_balance_zero_budget/use_balance_zero_budget.py @@ -27,5 +27,5 @@ def __init__(self): @gl.public.write def do_emit(self): gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) diff --git a/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.0.hash b/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.0.hash index 6bfe04d3..7ae0d621 100644 --- a/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.0.hash +++ b/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.0.hash @@ -1 +1 @@ -YEjh2sf3685jGHcRBX3KPfkENgKc63p4qYNDPpz5zVY= +GvHXAn+lSRbRXTgAQ20v9MIg+maJtyKY1vsqmGIL26I= diff --git a/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.0_0.hash b/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.0_0.hash index d73be2b9..1c36c76f 100644 --- a/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.0_0.hash +++ b/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.0_0.hash @@ -1 +1 @@ -6NAEnabWlHqltjP9g2o1NHhc+sxMGmmD5arc6zXk4ro= +rO2jxkEqIMkxE+njx0OumNOP6I6YK1PJR4AuuHLPadE= diff --git a/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.py b/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.py index e0426ef1..e183a6d4 100644 --- a/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.py +++ b/tests/integration/message/use_balance_zero_declared_budget/use_balance_zero_declared_budget.py @@ -24,5 +24,5 @@ def __init__(self): @gl.public.write def do_emit(self): gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) diff --git a/tests/integration/message/use_balance_zero_price/use_balance_zero_price.0.hash b/tests/integration/message/use_balance_zero_price/use_balance_zero_price.0.hash index 6c15397f..841d6068 100644 --- a/tests/integration/message/use_balance_zero_price/use_balance_zero_price.0.hash +++ b/tests/integration/message/use_balance_zero_price/use_balance_zero_price.0.hash @@ -1 +1 @@ -dk0oEblkdYk3km34GOV5pdk3D/wFIcxgmwwS3UyOyBY= +ZblofT/zWex0TUOtdkRGkZ4d76RNrl/dVS7Ib3AwRMU= diff --git a/tests/integration/message/use_balance_zero_price/use_balance_zero_price.0_0.hash b/tests/integration/message/use_balance_zero_price/use_balance_zero_price.0_0.hash index ab0e99a8..7a09707a 100644 --- a/tests/integration/message/use_balance_zero_price/use_balance_zero_price.0_0.hash +++ b/tests/integration/message/use_balance_zero_price/use_balance_zero_price.0_0.hash @@ -1 +1 @@ -17nZ+umGVnDh0htPWVu+yInAYr/EkqV8sDptCT2Q4Tg= +uuk+Rl4CJqCA8H/8pCgFi9GZCfXXYeHJndbnc0HwvZI= diff --git a/tests/integration/message/use_balance_zero_price/use_balance_zero_price.py b/tests/integration/message/use_balance_zero_price/use_balance_zero_price.py index d50e33da..a2e9f3d9 100644 --- a/tests/integration/message/use_balance_zero_price/use_balance_zero_price.py +++ b/tests/integration/message/use_balance_zero_price/use_balance_zero_price.py @@ -28,7 +28,7 @@ def do_emit(self): # use_balance with a zero price cap is rejected with Inval (errno 2). try: gl.contract.get_at(gl.Address(b'\x30' * 20)).emit( - use_balance=True, fee_params=_PARAMS + use_balance=gl.contract.UseBalanceParams(_PARAMS) ).foo(1, 2) except SystemError as e: print(e) diff --git a/tests/integration/misc/datetime/datetime.0.hash b/tests/integration/misc/datetime/datetime.0.hash index e7d545ca..84a01d7d 100644 --- a/tests/integration/misc/datetime/datetime.0.hash +++ b/tests/integration/misc/datetime/datetime.0.hash @@ -1 +1 @@ -JHPdT+QYCNXuCekIcsc9j2SYnCRDLEBpzsa3xkEutRQ= +dgqOcjyxwqREDxVFqilV4sOh+mRssH6ImxlpzHxQZNY= diff --git a/tests/integration/misc/floats/floats.0.hash b/tests/integration/misc/floats/floats.0.hash index f87e103f..5534577b 100644 --- a/tests/integration/misc/floats/floats.0.hash +++ b/tests/integration/misc/floats/floats.0.hash @@ -1 +1 @@ -c1i9ZO753tzaNwXrXwKmbXgXdFVUYJuzn4euBFZYIVU= +sMtmEXxIwBbULXZhygRZnPRjHoAiPvr63/En3sHnPxo= diff --git a/tests/integration/misc/formats/formats.0.hash b/tests/integration/misc/formats/formats.0.hash index 5710b8d7..4a3f14e4 100644 --- a/tests/integration/misc/formats/formats.0.hash +++ b/tests/integration/misc/formats/formats.0.hash @@ -1 +1 @@ -jPaW2T6M/RmP4eleaW9t/2aceEt5jtiUZtGujgd4pG8= +KMU45OEz5SSCNs1bs+RhX5Sq9ebMquHyHp6b7VHGpwU= diff --git a/tests/integration/misc/issue_163/issue_163.0.hash b/tests/integration/misc/issue_163/issue_163.0.hash index beb3b0a2..f1204ee4 100644 --- a/tests/integration/misc/issue_163/issue_163.0.hash +++ b/tests/integration/misc/issue_163/issue_163.0.hash @@ -1 +1 @@ -b6l1y8aZ8J2rl1thwkPOHlQVD0HlGw07ip7h/T4YyeI= +T4E2M7ZH46/19zO7wuZcgw41FG2gz4aEGl+342WjkQ4= diff --git a/tests/integration/misc/np/np.0.hash b/tests/integration/misc/np/np.0.hash index 506ddae3..38152b44 100644 --- a/tests/integration/misc/np/np.0.hash +++ b/tests/integration/misc/np/np.0.hash @@ -1 +1 @@ -W3BarK6AuLofcQt0OmEH1IqGhlRZternpyqCn/kxBWw= +wYB8s8/fBGJ57mnqxHJDgfBzU/Xi8RGxLWNqHfjda7A= diff --git a/tests/integration/misc/pil/pil.0.hash b/tests/integration/misc/pil/pil.0.hash index 57961b4d..efd2007d 100644 --- a/tests/integration/misc/pil/pil.0.hash +++ b/tests/integration/misc/pil/pil.0.hash @@ -1 +1 @@ -VBBiWeMuSYNb0Yw+qBHRVqtxAIBCK9C8jGuAnRVV9N4= +E5uu8Rzx1XK2GD026oZVJhIU8J0mGxFHWsBLwrwU9Bw= diff --git a/tests/integration/misc/re/re.0.hash b/tests/integration/misc/re/re.0.hash index 5f97d558..f1b914ec 100644 --- a/tests/integration/misc/re/re.0.hash +++ b/tests/integration/misc/re/re.0.hash @@ -1 +1 @@ -Tq7LeWY89IBAqaUqqDImVWdIm+FtC6ebwFSDTg+4d/w= +/h5rj97wmj6LO1zABr3DP5pa0bO/Pc0VjQWq9fS9TeA= diff --git a/tests/integration/misc/routed_call/routed_call.0.hash b/tests/integration/misc/routed_call/routed_call.0.hash index 927c609b..5e8692bb 100644 --- a/tests/integration/misc/routed_call/routed_call.0.hash +++ b/tests/integration/misc/routed_call/routed_call.0.hash @@ -1 +1 @@ -zVokEOKpsIangxfx7cefXHm0Q37uCV479YuSKz18tJQ= +EGBNd9TcHrhCgwRUOPeo5xs3xmnG5fYJ6bfjn2FOqjI= diff --git a/tests/integration/misc/routed_call/routed_call.0_0.hash b/tests/integration/misc/routed_call/routed_call.0_0.hash index 4ff7279d..3158b247 100644 --- a/tests/integration/misc/routed_call/routed_call.0_0.hash +++ b/tests/integration/misc/routed_call/routed_call.0_0.hash @@ -1 +1 @@ -Kab7LMZoAxR5cCDR13z4JfNckOEV15OfgeLgzBC7ew4= +Z2u2CXyh8rJIBnRsksFmNDM7RbUNyuKZ9he8Q8YW4FY= diff --git a/tests/integration/misc/routed_call/routed_call.0_0_0.hash b/tests/integration/misc/routed_call/routed_call.0_0_0.hash index 3240f372..1859ca3d 100644 --- a/tests/integration/misc/routed_call/routed_call.0_0_0.hash +++ b/tests/integration/misc/routed_call/routed_call.0_0_0.hash @@ -1 +1 @@ -jOKsPeWRc0uo3yE74NLtbCTlb5t50IwySdz9e+VU5MI= +NB+FNd/5kREfhrLxjx94L1sRg3obv+8w7nKPSlyGbYU= diff --git a/tests/integration/misc/typing_is_ok/typing_is_ok.0.hash b/tests/integration/misc/typing_is_ok/typing_is_ok.0.hash index 446c4b5a..7b320f6a 100644 --- a/tests/integration/misc/typing_is_ok/typing_is_ok.0.hash +++ b/tests/integration/misc/typing_is_ok/typing_is_ok.0.hash @@ -1 +1 @@ -rZJzeuWQkk0jZz7M//VhpNePLBmbxwZd34cQHmtF47w= +0Fs6SJWBEuhgfsjPr5h69GGdLUX/PB7Af7ZS8pQE90o= diff --git a/tests/integration/nasty-determinism/floats/floats.0.hash b/tests/integration/nasty-determinism/floats/floats.0.hash index 0d86b524..73e05a99 100644 --- a/tests/integration/nasty-determinism/floats/floats.0.hash +++ b/tests/integration/nasty-determinism/floats/floats.0.hash @@ -1 +1 @@ -lbPHus9kZ3S5YnhqwSY0Ya7samAzTlISN7fhd3FYYPw= +JiLXQxQs7/LdPXfu/693Hwqn6q3Qk7eHQA8YbDH+oSU= diff --git a/tests/integration/nasty-determinism/hash_random/hash_random.0.hash b/tests/integration/nasty-determinism/hash_random/hash_random.0.hash index bd6b912b..d970fc08 100644 --- a/tests/integration/nasty-determinism/hash_random/hash_random.0.hash +++ b/tests/integration/nasty-determinism/hash_random/hash_random.0.hash @@ -1 +1 @@ -FRMcK2zlq8lPmWkDvKBx8Cc8tuFnunkEH2LRnyKCaxY= +tTO+KQGoxPb2xYfYlItvp1i69yB3YhkRg7QlcKtsAeg= diff --git a/tests/integration/nasty-determinism/set_order/set_order.0.hash b/tests/integration/nasty-determinism/set_order/set_order.0.hash index 9456097b..479e6cbd 100644 --- a/tests/integration/nasty-determinism/set_order/set_order.0.hash +++ b/tests/integration/nasty-determinism/set_order/set_order.0.hash @@ -1 +1 @@ -cnY5/5++VZbENuE2aWFc5mDZXHTC99eqsqL3N7g0SNg= +yXf7lGO8gWdEkN2VNpADuaSDo2ifcRHr5oPe7aLz9e0= diff --git a/tests/integration/nondet-consensus/agree/agree.0.hash b/tests/integration/nondet-consensus/agree/agree.0.hash index bd0475de..79cd7981 100644 --- a/tests/integration/nondet-consensus/agree/agree.0.hash +++ b/tests/integration/nondet-consensus/agree/agree.0.hash @@ -1 +1 @@ -ttubOTGf9F2IcO2ueiBzAwS6bipGky3RJjmT+yD1hI4= +gjIxUsyewVM8iatpBXdHvwOywQnTQaxfxON/Kted6MA= diff --git a/tests/integration/nondet-consensus/agree/agree.0_0.hash b/tests/integration/nondet-consensus/agree/agree.0_0.hash index 36daf0a2..64550ed0 100644 --- a/tests/integration/nondet-consensus/agree/agree.0_0.hash +++ b/tests/integration/nondet-consensus/agree/agree.0_0.hash @@ -1 +1 @@ -rCPMLLOVdPPd8rw9bhfbkEEFzLrMeSMcpDctemtS42k= +Qz4jYjeQB6nOHhw/VRdFcUQRYOOhVGTv+fCLdTJJe+8= diff --git a/tests/integration/nondet-consensus/disagree/disagree.0.hash b/tests/integration/nondet-consensus/disagree/disagree.0.hash index bd0475de..79cd7981 100644 --- a/tests/integration/nondet-consensus/disagree/disagree.0.hash +++ b/tests/integration/nondet-consensus/disagree/disagree.0.hash @@ -1 +1 @@ -ttubOTGf9F2IcO2ueiBzAwS6bipGky3RJjmT+yD1hI4= +gjIxUsyewVM8iatpBXdHvwOywQnTQaxfxON/Kted6MA= diff --git a/tests/integration/nondet-consensus/disagree/disagree.0_0.hash b/tests/integration/nondet-consensus/disagree/disagree.0_0.hash index f3eb66b2..94ba8be7 100644 --- a/tests/integration/nondet-consensus/disagree/disagree.0_0.hash +++ b/tests/integration/nondet-consensus/disagree/disagree.0_0.hash @@ -1 +1 @@ -UoEA5AIxddIimAOKmtingL0g2MzVueznBrgOXMELjvw= +W06YSA5oDoHyQEkZof94xQjRvEjAuRydtO4WDOZd6lE= diff --git a/tests/integration/nondet-consensus/eq_prompt_non_comparative/eq_prompt_non_comparative_validator.0.hash b/tests/integration/nondet-consensus/eq_prompt_non_comparative/eq_prompt_non_comparative_validator.0.hash index fe528d9d..ba269e34 100644 --- a/tests/integration/nondet-consensus/eq_prompt_non_comparative/eq_prompt_non_comparative_validator.0.hash +++ b/tests/integration/nondet-consensus/eq_prompt_non_comparative/eq_prompt_non_comparative_validator.0.hash @@ -1 +1 @@ -6A07qvxIQeRoPt9qXICBW0VL0+IRpwDvHYDsW1ZwB0s= +9vemFsU8WhJOx5EKTWhU0+pE/QXmsWaJHPzy8Mk34GQ= diff --git a/tests/integration/nondet-consensus/eq_prompt_non_comparative/eq_prompt_non_comparative_validator_bad.0.hash b/tests/integration/nondet-consensus/eq_prompt_non_comparative/eq_prompt_non_comparative_validator_bad.0.hash index 65ac4bf9..5624bfac 100644 --- a/tests/integration/nondet-consensus/eq_prompt_non_comparative/eq_prompt_non_comparative_validator_bad.0.hash +++ b/tests/integration/nondet-consensus/eq_prompt_non_comparative/eq_prompt_non_comparative_validator_bad.0.hash @@ -1 +1 @@ -qCpBg9szSv5OgRdF+/oMetRlYEIM6xrwR4uMwl/4vLY= +hND7m7Xr2ubdWzaatQRSSgVGFAEqIILQoVvI5LaeYQk= diff --git a/tests/integration/nondet-consensus/leader_errors/empty_leader_result.0.hash b/tests/integration/nondet-consensus/leader_errors/empty_leader_result.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/empty_leader_result.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/empty_leader_result.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/empty_leader_result.0_0.hash b/tests/integration/nondet-consensus/leader_errors/empty_leader_result.0_0.hash index 99e82c97..ffddad5a 100644 --- a/tests/integration/nondet-consensus/leader_errors/empty_leader_result.0_0.hash +++ b/tests/integration/nondet-consensus/leader_errors/empty_leader_result.0_0.hash @@ -1 +1 @@ -kGrUtQ+f0AJD/3YIt9RpHIeoEnwuMotrRkG2SNb+k7E= +qow8NFYNvLIGZZ4X/qmdqEypPb75AoKI05lTMO4pK2Y= diff --git a/tests/integration/nondet-consensus/leader_errors/leader_no_nondet.0.hash b/tests/integration/nondet-consensus/leader_errors/leader_no_nondet.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/leader_no_nondet.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/leader_no_nondet.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/leader_no_nondet.0_0.hash b/tests/integration/nondet-consensus/leader_errors/leader_no_nondet.0_0.hash index 99e82c97..ffddad5a 100644 --- a/tests/integration/nondet-consensus/leader_errors/leader_no_nondet.0_0.hash +++ b/tests/integration/nondet-consensus/leader_errors/leader_no_nondet.0_0.hash @@ -1 +1 @@ -kGrUtQ+f0AJD/3YIt9RpHIeoEnwuMotrRkG2SNb+k7E= +qow8NFYNvLIGZZ4X/qmdqEypPb75AoKI05lTMO4pK2Y= diff --git a/tests/integration/nondet-consensus/leader_errors/malformed_leader_public_data.0.hash b/tests/integration/nondet-consensus/leader_errors/malformed_leader_public_data.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/malformed_leader_public_data.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/malformed_leader_public_data.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_code.0.hash b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_code.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_code.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_code.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_code.0_0.hash b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_code.0_0.hash index 898ca370..6e56c6b9 100644 --- a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_code.0_0.hash +++ b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_code.0_0.hash @@ -1 +1 @@ -Yptz3uCUkA11hZ+Trv/gkKO1yXkFVJ3XBEazA74JneY= +5uLbYBAoCAr8KR1wnnl4WrLT6LkhWKpxgOZzKkM7TZI= diff --git a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_return.0.hash b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_return.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_return.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_return.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_return.0_0.hash b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_return.0_0.hash index 898ca370..6e56c6b9 100644 --- a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_return.0_0.hash +++ b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_return.0_0.hash @@ -1 +1 @@ -Yptz3uCUkA11hZ+Trv/gkKO1yXkFVJ3XBEazA74JneY= +5uLbYBAoCAr8KR1wnnl4WrLT6LkhWKpxgOZzKkM7TZI= diff --git a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_vm_error.0.hash b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_vm_error.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_vm_error.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_vm_error.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_vm_error.0_0.hash b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_vm_error.0_0.hash index 898ca370..6e56c6b9 100644 --- a/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_vm_error.0_0.hash +++ b/tests/integration/nondet-consensus/leader_errors/malformed_leader_result_vm_error.0_0.hash @@ -1 +1 @@ -Yptz3uCUkA11hZ+Trv/gkKO1yXkFVJ3XBEazA74JneY= +5uLbYBAoCAr8KR1wnnl4WrLT6LkhWKpxgOZzKkM7TZI= diff --git a/tests/integration/nondet-consensus/leader_errors/simple_leader.0.hash b/tests/integration/nondet-consensus/leader_errors/simple_leader.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/simple_leader.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/simple_leader.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/simple_leader.0_0.hash b/tests/integration/nondet-consensus/leader_errors/simple_leader.0_0.hash index 96721a64..340bc881 100644 --- a/tests/integration/nondet-consensus/leader_errors/simple_leader.0_0.hash +++ b/tests/integration/nondet-consensus/leader_errors/simple_leader.0_0.hash @@ -1 +1 @@ -O0Aj50y5e7MHo03b5LH9jZmL608DHyC/kkOgUxIam70= +C0XvbCYJ9bdHTtMAJNexIu7oP42Kzp8QyxvIetvQfbk= diff --git a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_err.0.hash b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_err.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_err.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_err.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_err.0_0.hash b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_err.0_0.hash index 96721a64..340bc881 100644 --- a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_err.0_0.hash +++ b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_err.0_0.hash @@ -1 +1 @@ -O0Aj50y5e7MHo03b5LH9jZmL608DHyC/kkOgUxIam70= +C0XvbCYJ9bdHTtMAJNexIu7oP42Kzp8QyxvIetvQfbk= diff --git a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit.0.hash b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit.0_0.hash b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit.0_0.hash index 6b3e4715..32add440 100644 --- a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit.0_0.hash +++ b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit.0_0.hash @@ -1 +1 @@ -8wwk4UKDNPTbwVcfuJ73ZIEE8axszvZVU/8uzCvYBAE= +16AKxGr0BXjzb4BP5d26LVR6JeR7/n2NuYYrTZd/2CU= diff --git a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit_wrong_err.0.hash b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit_wrong_err.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit_wrong_err.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit_wrong_err.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash index 495411d7..f9e86d40 100644 --- a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash +++ b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_exit_wrong_err.0_0.hash @@ -1 +1 @@ -sMvtY7A8aEaGPaHDBjODZ5jk2LuwXM6d1dClCc8yzyw= +IkCkO9LDGQ2BY6UpUi9FgvfkcICCP2w1tPgoXz6LXQY= diff --git a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_nerr.0.hash b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_nerr.0.hash index 170922bf..b92e7ac6 100644 --- a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_nerr.0.hash +++ b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_nerr.0.hash @@ -1 +1 @@ -VSIyKWieNP5zzAusn1CfhiBW3qbpHXyUtbwY/sweVlk= +SZZT/jvLkSNPrKjMtNYb51kPjxq8qT42zwIYIlL5mEo= diff --git a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_nerr.0_0.hash b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_nerr.0_0.hash index 561e336b..378eb5f5 100644 --- a/tests/integration/nondet-consensus/leader_errors/simple_valid_err_nerr.0_0.hash +++ b/tests/integration/nondet-consensus/leader_errors/simple_valid_err_nerr.0_0.hash @@ -1 +1 @@ -KrcbX9ZKWypZ1jTRyBFIT+sGXjQERa9Mh/ckPSithVw= +4SMtnP1osjSdEb5SM66Yxjciu02qbwSle7Ha42Vm2ng= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.3r3m4s.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.3r3m4s.hash index 1b674801..645717fc 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.3r3m4s.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.3r3m4s.hash @@ -1 +1 @@ -8DV+4hW7XgNY7ib9KXYmLCz+GwbliT4Ou7t4EWq9ZEw= +hTvbdoLuEy7hR220J0qNQo/PAdKl7aWCorcm1Dj2G4s= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.48n4pv.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.48n4pv.hash index e8fd13bc..1474dfe5 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.48n4pv.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.48n4pv.hash @@ -1 +1 @@ -qOgLSGQMfWJE2bhgGXje6K+CwI5Lv/iqUPavg2xJ2rE= +nlr3MzDPRFzmRuKRNDymBLcdo/0GKXt2G0jmel4bmCo= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.bccnkg.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.bccnkg.hash index d230ad08..eb405b9e 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.bccnkg.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.bccnkg.hash @@ -1 +1 @@ -yxC9UIeFvdYyNAHD5pVBpy0PRr8DxcigBtREkaqMQY4= +sWJldg4qo0OMoJFSEdMFEhlgfCKPN3yB5bdBZrnZeWE= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.bw2cm8.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.bw2cm8.hash index d91c34a7..913b880b 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.bw2cm8.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.bw2cm8.hash @@ -1 +1 @@ -nQiBt3cpsG3Xk8JQbEeAfaCpexQwObxsQch455o/15E= +uegXwFDJefrP/zntjK/KfWwpXh/P9EpG20GREBclqvs= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.ece46b.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.ece46b.hash index 60f1ab5f..80fdc88c 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.ece46b.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.ece46b.hash @@ -1 +1 @@ -MQ+Fqhe46qgHB4u+mhweOfpxihT8iKm3qW9D/m+TOj4= +LXXKGiUR3O4IPhirzu8icJUI8UaIl+GTG1+4B1q6ICc= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.fwxcex.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.fwxcex.hash index 803fc522..1f4007ef 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.fwxcex.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.fwxcex.hash @@ -1 +1 @@ -biewr2x6mXgXqHUK1dQmH42CknOZM/MCXUR2ECfu8Fc= +JJsVYUoEWiMHg+vcqBJa4zX1aj6itj/4Top6GqSN5UY= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.gatqf1.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.gatqf1.hash index 9a631347..ad49dda1 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.gatqf1.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.gatqf1.hash @@ -1 +1 @@ -y8/iJ4QGvfNPAmPD2mh8P3jXAvNgUBhPs4APzjvSANE= +bbVkG9PGZ+4YT3DdyJzZeTKYMi2RUkQ8HQLgARR7WkY= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.hh9tce.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.hh9tce.hash index ba732ac2..a8564a57 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.hh9tce.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.hh9tce.hash @@ -1 +1 @@ -FauG5hycYnD4eKa+AhBBWavHLzQQbsP//76AC0Vl1X8= +zcGGylD83WLCUXsrD67IncU7CW0Tebtnc/1Qzmn+Ucg= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.mkdxq9.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.mkdxq9.hash index 098b4c94..9601db14 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.mkdxq9.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.mkdxq9.hash @@ -1 +1 @@ -wwI6MBlyNk191E1gJOw47GRKw8s5zdh/a9HD1WeV/Gw= +LBR6vqbUvMSgCNlOWfIW5OgEoilx9tUX48jq2XW3klY= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.q2bhfw.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.q2bhfw.hash index b73411af..44285d61 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.q2bhfw.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.q2bhfw.hash @@ -1 +1 @@ -rdM3kE/dW9cTdoJfMUj7AIWspIqg7ETGogXb3373YNA= +xxZSmj7PS0iLT8/lt1auABSIh7nXPHwp7kux2liicsc= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.q7j6m9.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.q7j6m9.hash index aeab2e91..bca27942 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.q7j6m9.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.q7j6m9.hash @@ -1 +1 @@ -Tm2+8Mq0XMlReSnaw1nIYApLSvvYl7YAa18YlCxo6a8= +t1a8irgjB89M9yh0o5fidOzvvD8Zkvin4HZm2jKDqto= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.qg88x4.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.qg88x4.hash index 04906e0b..f4ef7eae 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.qg88x4.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.qg88x4.hash @@ -1 +1 @@ -57fgnwwkYz0sMobprhsquiUsAXs2Ei5NYHJOMksk9u4= +R4ttbahK4tYDDQsnPRI2czq6tLqFT7S/LCX+Mq7vgJ4= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.qhv9g7.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.qhv9g7.hash index b480e7bb..8a4f7d59 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.qhv9g7.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.qhv9g7.hash @@ -1 +1 @@ -Dia5fTTzFgW0Y4WmyaQFi7m5gI+xuPgNeAMvRai3ac0= +m3KrM2ihl4zIXWudo/Bo+3w6Jmr5jg44Pa+x9QehGNY= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.rf2yq1.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.rf2yq1.hash index f7e739c2..d8c79999 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.rf2yq1.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.rf2yq1.hash @@ -1 +1 @@ -7tdBZpMKa1hVp01JWvIxYMkUPMf3Ari2jQ5G68libyU= +BK9ku2wHaf+xYgHt2f+s4+qoB7jkrzrlh6TnUPjOBCY= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.tkryxe.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.tkryxe.hash index 9ad4129f..51dd9723 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.tkryxe.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.tkryxe.hash @@ -1 +1 @@ -aUVqyxm1FVZoPXZzz262bXn3YmtpN1TSdWudHyHfAmU= +9id2zgDA0ikDi57y6YASRoyEXW98AFwt83kssplWtS8= diff --git a/tests/integration/nondet-consensus/malicious-leader/ret/ret.zk395p.hash b/tests/integration/nondet-consensus/malicious-leader/ret/ret.zk395p.hash index d13d0227..55be3359 100644 --- a/tests/integration/nondet-consensus/malicious-leader/ret/ret.zk395p.hash +++ b/tests/integration/nondet-consensus/malicious-leader/ret/ret.zk395p.hash @@ -1 +1 @@ -QI48v6v+DsMUvh0Kg5Dy5q9Wce0wFGtorSiE03A0a2M= +J9ArGCjhcdShlq2Ji8mWZUYtM4M90gA+zHqrnO9p4PY= diff --git a/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0.hash b/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0.hash index 6b486331..d315190b 100644 --- a/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0.hash +++ b/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0.hash @@ -1 +1 @@ -gMDXCLWLiKBfL7VReID7W2hvu6u0kiDbNVjfUcY7r4o= +68L22jmie6bcPC3K69AErSv6sIDwSN29Hf7hunOY4uc= diff --git a/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_0.hash b/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_0.hash index 58642356..44a8d8dd 100644 --- a/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_0.hash +++ b/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_0.hash @@ -1 +1 @@ -E2ytn/FWvDwKavKImN9cLLh4JpeNNZNYY8YJS9hOdHw= +W0p4/A8vsueWrMSiLw4PFHUmixbOmbwebdexu8lTarw= diff --git a/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_1.hash b/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_1.hash index b2029150..439649d3 100644 --- a/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_1.hash +++ b/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_1.hash @@ -1 +1 @@ -bg2XH5SzC9zDudN7DeApsVLPhYY6glDRgIHPdJa6Hvo= +heKkmCRG/gSS2VtwbXa/MHHBJCYRRsQVChjb02rcKiM= diff --git a/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_2.hash b/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_2.hash index 8cdb4488..b011522b 100644 --- a/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_2.hash +++ b/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_2.hash @@ -1 +1 @@ -Tbifs9bd6jW7HX85b7ruc2c8h3wQeoYKBc9ALBQHD/I= +JluKFVXz0Rk+RiNQMwqPfnAauZdq+FmiOGjHSTa5WtE= diff --git a/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_3.hash b/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_3.hash index 4ad7b66a..e04f0482 100644 --- a/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_3.hash +++ b/tests/integration/nondet-consensus/output_fee_cap/output_fee_cap.0_3.hash @@ -1 +1 @@ -OwFt4SMhOALz/9SbQI7aANuZOo4cd9QXGhge0WwMuSM= +61FqT3MX8ltYxtNwoxNXk3Dxma1IJFBa21wVofVg/uQ= diff --git a/tests/integration/nondet-consensus/rollback/rollback_agree.0.hash b/tests/integration/nondet-consensus/rollback/rollback_agree.0.hash index 7900bebb..a69ee086 100644 --- a/tests/integration/nondet-consensus/rollback/rollback_agree.0.hash +++ b/tests/integration/nondet-consensus/rollback/rollback_agree.0.hash @@ -1 +1 @@ -yx5/kc4N/Y5z0bgLf5Jua4uYDByGmjRis/j3zFTwYL8= +ZNJH9sF8fcUkNQ7ArlrkAzG7j5QLieVqDWdFuYPm8cA= diff --git a/tests/integration/nondet-consensus/rollback/rollback_agree.0_0.hash b/tests/integration/nondet-consensus/rollback/rollback_agree.0_0.hash index 309e22fc..ecec9f7e 100644 --- a/tests/integration/nondet-consensus/rollback/rollback_agree.0_0.hash +++ b/tests/integration/nondet-consensus/rollback/rollback_agree.0_0.hash @@ -1 +1 @@ -vyU7VXfTOGzGqWThEvNPDLjsDJu3AF+ZVBV37V4gEmg= +d2r2v1mE/GKU4VR+Me8yQKh2bx0aKIzILjKh1rImJHE= diff --git a/tests/integration/nondet-consensus/rollback/rollback_disagree.0.hash b/tests/integration/nondet-consensus/rollback/rollback_disagree.0.hash index 7900bebb..a69ee086 100644 --- a/tests/integration/nondet-consensus/rollback/rollback_disagree.0.hash +++ b/tests/integration/nondet-consensus/rollback/rollback_disagree.0.hash @@ -1 +1 @@ -yx5/kc4N/Y5z0bgLf5Jua4uYDByGmjRis/j3zFTwYL8= +ZNJH9sF8fcUkNQ7ArlrkAzG7j5QLieVqDWdFuYPm8cA= diff --git a/tests/integration/nondet-consensus/rollback/rollback_disagree.0_0.hash b/tests/integration/nondet-consensus/rollback/rollback_disagree.0_0.hash index 20da36d3..e56bc230 100644 --- a/tests/integration/nondet-consensus/rollback/rollback_disagree.0_0.hash +++ b/tests/integration/nondet-consensus/rollback/rollback_disagree.0_0.hash @@ -1 +1 @@ -tKfMKwq+2k2ZZheFFu4dd3ftviALx6uZK71PskYrCtE= +3QS5ALXlm+LQ84MMKTw0qZ4ninRsSeHtqGJ1T4W1bqA= diff --git a/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0.hash b/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0.hash index dc28fe6d..698542dd 100644 --- a/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0.hash +++ b/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0.hash @@ -1 +1 @@ -uIWKho7MH5t1PIspsqdpuCxmNdCXMynwY5xZdarYmUo= +3xpXLlMp7PyII4d0QvaDOq4meBQy7nL+tPO9OMIn0Ps= diff --git a/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_0.hash b/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_0.hash index ddd4cef1..416106cc 100644 --- a/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_0.hash +++ b/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_0.hash @@ -1 +1 @@ -JvmoWx0dC6W6kr+2VEj7pZyqf0JWFZpZJsomhgVQAIU= +RsJofYEggKVTuf5GURYYUGIBiXXX+j57FWDLj1pVO9M= diff --git a/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_1.hash b/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_1.hash index 77a8de21..44b97a4f 100644 --- a/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_1.hash +++ b/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_1.hash @@ -1 +1 @@ -x8FBJKLSs1Wj6a40q+p8m1B72ITqIKhjBFvqvqoDJSc= +AMZRqSv94xwqCt6EOxBL23Dd1y8A3aegDVx1pntxpGM= diff --git a/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_2.hash b/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_2.hash index ff6dd376..535352b7 100644 --- a/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_2.hash +++ b/tests/integration/nondet-consensus/rollback_imm/rollback_imm.0_2.hash @@ -1 +1 @@ -MiAYrmA/vaXcrO79e8uXxSqtlmvJlyMkfgF5LlgI2z0= +rrwSIP9xW4UTHzkx2o/Z0RpQSYEsQ5fIm/mSzZfIPRk= diff --git a/tests/integration/nondet-consensus/single_worker/single_worker.0.hash b/tests/integration/nondet-consensus/single_worker/single_worker.0.hash index b4a96226..19c1b9f9 100644 --- a/tests/integration/nondet-consensus/single_worker/single_worker.0.hash +++ b/tests/integration/nondet-consensus/single_worker/single_worker.0.hash @@ -1 +1 @@ -uAaiTXCOQFv/R+7XR0hhtIqczGhkmVeVwE4tCM35vwM= +n3pF0HUhrh8166eN9mka5D4KbCVlnZL0wM/tWyIFM/E= diff --git a/tests/integration/nondet-consensus/sync/sync.0.hash b/tests/integration/nondet-consensus/sync/sync.0.hash index 2bcf64e6..7694bb55 100644 --- a/tests/integration/nondet-consensus/sync/sync.0.hash +++ b/tests/integration/nondet-consensus/sync/sync.0.hash @@ -1 +1 @@ -3/RsBPIQxbzPESzhlgwzIS7HRus1S2ivOwNo0dlQUgQ= +YDtht4Cf7yPFv/J/8cLGfrEbRhKTWJ78pje71bJy7+E= diff --git a/tests/integration/nondet-consensus/sync/sync.0_0.hash b/tests/integration/nondet-consensus/sync/sync.0_0.hash index 39308119..c06609f6 100644 --- a/tests/integration/nondet-consensus/sync/sync.0_0.hash +++ b/tests/integration/nondet-consensus/sync/sync.0_0.hash @@ -1 +1 @@ -WAUKCrQOJkyJlbd/jl8kiY8usPxnAJMqydGw75gMFOQ= +9FAx9z9jfMxS/xErqA/Y1MLZqpZ6owCEYwo7n+jE1uI= diff --git a/tests/integration/nondet-consensus/sync/sync_err.0.hash b/tests/integration/nondet-consensus/sync/sync_err.0.hash index 2bcf64e6..7694bb55 100644 --- a/tests/integration/nondet-consensus/sync/sync_err.0.hash +++ b/tests/integration/nondet-consensus/sync/sync_err.0.hash @@ -1 +1 @@ -3/RsBPIQxbzPESzhlgwzIS7HRus1S2ivOwNo0dlQUgQ= +YDtht4Cf7yPFv/J/8cLGfrEbRhKTWJ78pje71bJy7+E= diff --git a/tests/integration/nondet-consensus/sync/sync_err.0_0.hash b/tests/integration/nondet-consensus/sync/sync_err.0_0.hash index b66b2e91..5492ec85 100644 --- a/tests/integration/nondet-consensus/sync/sync_err.0_0.hash +++ b/tests/integration/nondet-consensus/sync/sync_err.0_0.hash @@ -1 +1 @@ -2M0DJF84Ma1etedcwS3nAahQ9RyCIIXJth+yUb0OlJM= +On0d14iHxzARWbqEO+OPWYp1tdpowVu3pn6QUlzuwMM= diff --git a/tests/integration/permission/method_init/method_init.0.hash b/tests/integration/permission/method_init/method_init.0.hash index 513e45c2..3486d62a 100644 --- a/tests/integration/permission/method_init/method_init.0.hash +++ b/tests/integration/permission/method_init/method_init.0.hash @@ -1 +1 @@ -NTXtthDJvkIoJWCPA/T1s9GYvkErzIXTtr96heSXM8A= +AgDUZC3M/EqHb8q+nC80IS5jGI3MmfdlhU5TYgpdGc4= diff --git a/tests/integration/permission/method_init/method_init.0_0.hash b/tests/integration/permission/method_init/method_init.0_0.hash index b750317c..3d4ccb80 100644 --- a/tests/integration/permission/method_init/method_init.0_0.hash +++ b/tests/integration/permission/method_init/method_init.0_0.hash @@ -1 +1 @@ -7YdWInLP0iJ632u8OJyWkFzIT+04agcJpolwxY/O1NI= +cqYDKsq/MHkRwL85qibLlyZS/B63h9KmhQKTH4W14d8= diff --git a/tests/integration/permission/method_private/method_private.0.hash b/tests/integration/permission/method_private/method_private.0.hash index cf93c05d..39887a36 100644 --- a/tests/integration/permission/method_private/method_private.0.hash +++ b/tests/integration/permission/method_private/method_private.0.hash @@ -1 +1 @@ -hJcMexFEaOQ1VRIRlGV3SDy97RDMYFtWKuRP3MGGi9w= +b9ea3H+PFvgPP1j+e+5IG5/jjXFlQAdQqGyn04Wck3g= diff --git a/tests/integration/permission/method_private/method_private.0_0.hash b/tests/integration/permission/method_private/method_private.0_0.hash index 68331058..a0f16630 100644 --- a/tests/integration/permission/method_private/method_private.0_0.hash +++ b/tests/integration/permission/method_private/method_private.0_0.hash @@ -1 +1 @@ -NH+poPzpMbvd1qvxI4GIXR6rZOLbx3+P28wS7cqvpWI= +In+1yHuz3rtMjTanmR9EE9DRmXv9fYF/pxnrwkbFG5c= diff --git a/tests/integration/permission/metod_det_get_webpage/metod_det_get_webpage.0.hash b/tests/integration/permission/metod_det_get_webpage/metod_det_get_webpage.0.hash index a7bb267a..4059c52d 100644 --- a/tests/integration/permission/metod_det_get_webpage/metod_det_get_webpage.0.hash +++ b/tests/integration/permission/metod_det_get_webpage/metod_det_get_webpage.0.hash @@ -1 +1 @@ -XovElmr3T73yia11KjnEkuMKLPsrdMij/kenSZ6S2ak= +ENoR84NrLkLr234M2LtugZEjoQ5iuNYaqr5DJJXF/vY= diff --git a/tests/integration/permission/metod_det_get_webpage/metod_det_get_webpage.0_0.hash b/tests/integration/permission/metod_det_get_webpage/metod_det_get_webpage.0_0.hash index 2091ccd5..d052ddd4 100644 --- a/tests/integration/permission/metod_det_get_webpage/metod_det_get_webpage.0_0.hash +++ b/tests/integration/permission/metod_det_get_webpage/metod_det_get_webpage.0_0.hash @@ -1 +1 @@ -eDLsPAMJz+RUr5wFkhELqrEh4MQ0HrHlt86ThCXF0vo= +lEsd8sdGTqqf6/UqCcrO1AxGFU7FRo3lWZ8vpx8sH3M= diff --git a/tests/integration/prompt/embeddings_long/embeddings_long.0.hash b/tests/integration/prompt/embeddings_long/embeddings_long.0.hash index d88ef3a4..85815461 100644 --- a/tests/integration/prompt/embeddings_long/embeddings_long.0.hash +++ b/tests/integration/prompt/embeddings_long/embeddings_long.0.hash @@ -1 +1 @@ -HRxohn0Z1lyK2B0jm/0vVJJGe1ZOavbFbP8ef/darRk= +XLQTaZP/KiwxLyrXW7POaQ1YUNfJ9YZVnPadyd/i7Ao= diff --git a/tests/integration/prompt/embeddings_long/embeddings_long.0_0.hash b/tests/integration/prompt/embeddings_long/embeddings_long.0_0.hash index f73d1ed1..3ca2f075 100644 --- a/tests/integration/prompt/embeddings_long/embeddings_long.0_0.hash +++ b/tests/integration/prompt/embeddings_long/embeddings_long.0_0.hash @@ -1 +1 @@ -bPkkT0mOYl5s07HU9XVwgb8WREXWOkaP/OMUcxU73Jw= +IjmZusR922q9hQMOngRJHJ7bWN/ftkikD4xwbQ21Q14= diff --git a/tests/integration/prompt/embeddings_long/embeddings_long_det.0.hash b/tests/integration/prompt/embeddings_long/embeddings_long_det.0.hash index d88ef3a4..85815461 100644 --- a/tests/integration/prompt/embeddings_long/embeddings_long_det.0.hash +++ b/tests/integration/prompt/embeddings_long/embeddings_long_det.0.hash @@ -1 +1 @@ -HRxohn0Z1lyK2B0jm/0vVJJGe1ZOavbFbP8ef/darRk= +XLQTaZP/KiwxLyrXW7POaQ1YUNfJ9YZVnPadyd/i7Ao= diff --git a/tests/integration/prompt/embeddings_long/embeddings_long_det.0_0.hash b/tests/integration/prompt/embeddings_long/embeddings_long_det.0_0.hash index 0a8f3e04..9a3013ca 100644 --- a/tests/integration/prompt/embeddings_long/embeddings_long_det.0_0.hash +++ b/tests/integration/prompt/embeddings_long/embeddings_long_det.0_0.hash @@ -1 +1 @@ -yIWe6eecnF/ATFaf1jIfdZ24RTRZeRqFIa+cGb2x5Bc= +w3H8bgC5RLaKM5Lc+5BJA10XnEqC2eMyI7/cU23iF0Q= diff --git a/tests/integration/prompt/get_webpage_screenshot/get_webpage_screenshot.0.hash b/tests/integration/prompt/get_webpage_screenshot/get_webpage_screenshot.0.hash index fde42938..38df2178 100644 --- a/tests/integration/prompt/get_webpage_screenshot/get_webpage_screenshot.0.hash +++ b/tests/integration/prompt/get_webpage_screenshot/get_webpage_screenshot.0.hash @@ -1 +1 @@ -/2EVbDl9OP6pHtBrkt5lwpWL86oU0mDQlqsl+1LLJaQ= +Rs7LpBqxns3qdJiZdTASzD5vLl5otjWz8mRQknaNLHk= diff --git a/tests/integration/prompt/percent_in_prompt/percent_in_prompt.0.hash b/tests/integration/prompt/percent_in_prompt/percent_in_prompt.0.hash index ab727f8e..6da6aaac 100644 --- a/tests/integration/prompt/percent_in_prompt/percent_in_prompt.0.hash +++ b/tests/integration/prompt/percent_in_prompt/percent_in_prompt.0.hash @@ -1 +1 @@ -otzOkaR4JplG8OQ/JsHUPAmV8sebMXWYHW5INXJBNZ4= +1tC+0PRqYMfbvtUaFhjZCTqVOOuwBi0DWjfn+I/dokg= diff --git a/tests/integration/prompt/simple/simple.0.hash b/tests/integration/prompt/simple/simple.0.hash index 9897b338..572882de 100644 --- a/tests/integration/prompt/simple/simple.0.hash +++ b/tests/integration/prompt/simple/simple.0.hash @@ -1 +1 @@ -jNgu/UzF+uszYvmV4Ttjb/dDc0+iiIoqfzmlRrjhC+Q= +Tz/6VxcHx6s95H2UQxZH0+nfl+gaE6pH8Gxok1AvNH4= diff --git a/tests/integration/prompt/simple/simple.0_0.hash b/tests/integration/prompt/simple/simple.0_0.hash index 2718996b..31b0a72a 100644 --- a/tests/integration/prompt/simple/simple.0_0.hash +++ b/tests/integration/prompt/simple/simple.0_0.hash @@ -1 +1 @@ -6/fKmIWCuWet01KQCgxE+ATjICOv1JomL5ENdUdIlRY= +InOXWd1K6EiKyWg+boG5/xfc/SiRXf2oG9Mu3YW1Ku4= diff --git a/tests/integration/prompt/simple/simple_det.0.hash b/tests/integration/prompt/simple/simple_det.0.hash index 9897b338..572882de 100644 --- a/tests/integration/prompt/simple/simple_det.0.hash +++ b/tests/integration/prompt/simple/simple_det.0.hash @@ -1 +1 @@ -jNgu/UzF+uszYvmV4Ttjb/dDc0+iiIoqfzmlRrjhC+Q= +Tz/6VxcHx6s95H2UQxZH0+nfl+gaE6pH8Gxok1AvNH4= diff --git a/tests/integration/prompt/simple/simple_det.0_0.hash b/tests/integration/prompt/simple/simple_det.0_0.hash index 48f9df80..30808ccc 100644 --- a/tests/integration/prompt/simple/simple_det.0_0.hash +++ b/tests/integration/prompt/simple/simple_det.0_0.hash @@ -1 +1 @@ -dBugQxM3oDmzmj9mmULjELZnnAPZzPRoxVk5g0u5rIk= +g0qAEP2QadevgIwI9l8IQyiJsKcorkaCEoOXvpimmWc= diff --git a/tests/integration/prompt/simple_tokenizer/simple_tokenizer.0.hash b/tests/integration/prompt/simple_tokenizer/simple_tokenizer.0.hash index 99ecaa31..513455c8 100644 --- a/tests/integration/prompt/simple_tokenizer/simple_tokenizer.0.hash +++ b/tests/integration/prompt/simple_tokenizer/simple_tokenizer.0.hash @@ -1 +1 @@ -uAP0vtjezv/NCYjUhfzDs629Cs5Q/qen/DzTtDAtepc= +yWjmid2edsVrxtLOGJEFYA+sYL1HrAW7BzdtC5IV8LY= diff --git a/tests/integration/prompt/simple_tokenizer/simple_tokenizer.0_0.hash b/tests/integration/prompt/simple_tokenizer/simple_tokenizer.0_0.hash index f223dd5f..4371279c 100644 --- a/tests/integration/prompt/simple_tokenizer/simple_tokenizer.0_0.hash +++ b/tests/integration/prompt/simple_tokenizer/simple_tokenizer.0_0.hash @@ -1 +1 @@ -zyMWVBSnfKMj2im/NdqkALfzmUdgOINFYbLAi0HWAlY= +1hY7Dyj1tByNEH2Mobe2vMnKL2UJOVWKSz+qNIIRJcQ= diff --git a/tests/integration/runner/dup-dependency/dup-dependency.0.hash b/tests/integration/runner/dup-dependency/dup-dependency.0.hash index 759993ce..94504a2a 100644 --- a/tests/integration/runner/dup-dependency/dup-dependency.0.hash +++ b/tests/integration/runner/dup-dependency/dup-dependency.0.hash @@ -1 +1 @@ -HQbIv0mF4O3tH7HrLS/0Dpj7R+SA3kf8xp5frbKQ4zQ= +FGFufxTyO7/cHco2bTblB9vuljzlYdrAJPX4cgYH3uo= diff --git a/tests/integration/runner/env-template/env-template.0.hash b/tests/integration/runner/env-template/env-template.0.hash index 4cf8beae..81dc6de6 100644 --- a/tests/integration/runner/env-template/env-template.0.hash +++ b/tests/integration/runner/env-template/env-template.0.hash @@ -1 +1 @@ -GKYBy+/qzyvH/y/TI97H5AaLY/3yYZy2Lwlq1CPzkXo= +P1x1+WVkPkZ08jd9BspBgJ542YfdTcJ5RyQIaEur0Ak= diff --git a/tests/integration/runner/multi_contract/multi_contract.0.hash b/tests/integration/runner/multi_contract/multi_contract.0.hash index a0d3be19..1f7e5836 100644 --- a/tests/integration/runner/multi_contract/multi_contract.0.hash +++ b/tests/integration/runner/multi_contract/multi_contract.0.hash @@ -1 +1 @@ -9jc3fF6rsFrOCINmHFB/aFBH5I+VZQGa58eXWVdLlGU= +KY7Wm2Jo8cH2brEYXYo4RDLWhxcDLkwTRUVGUAZdIZo= diff --git a/tests/integration/runner/nondet_custom_runner/nondet_custom_runner.0.hash b/tests/integration/runner/nondet_custom_runner/nondet_custom_runner.0.hash index 77d8e293..a1ad1c4a 100644 --- a/tests/integration/runner/nondet_custom_runner/nondet_custom_runner.0.hash +++ b/tests/integration/runner/nondet_custom_runner/nondet_custom_runner.0.hash @@ -1 +1 @@ -dD3skNEjKRtHcToElooFSm1Lj1zferdyRaLbQAPTjpc= +E76FTCOuc+IYbrsrBzBPYpKKRbYm59VISP/qsCUx1E8= diff --git a/tests/integration/runner/zip/no-zip.0.hash b/tests/integration/runner/zip/no-zip.0.hash index a5f5d31a..c783b95b 100644 --- a/tests/integration/runner/zip/no-zip.0.hash +++ b/tests/integration/runner/zip/no-zip.0.hash @@ -1 +1 @@ -lsVSz84xXRJHQD1PDLfZkwAsbnuNs0Yr1rKJ2OeefVA= +udEG67hUInX2KGCStvI+qNyNKQiC49ymq8llu/5nDUM= diff --git a/tests/integration/sandbox/det/s/assign-json.0.hash b/tests/integration/sandbox/det/s/assign-json.0.hash index 045af958..dbf57fe2 100644 --- a/tests/integration/sandbox/det/s/assign-json.0.hash +++ b/tests/integration/sandbox/det/s/assign-json.0.hash @@ -1 +1 @@ -x3CBwGnyoVhBvq5/VvDraCJlPVBb5Jxdce6Ti8iU9gc= +g8wXDWJLYOFbRqofkeuXHbP5V9Wm8bT2R+sqF7tNwqM= diff --git a/tests/integration/sandbox/det/s/assign-json.0_0.hash b/tests/integration/sandbox/det/s/assign-json.0_0.hash index c9977e07..ab39f6b9 100644 --- a/tests/integration/sandbox/det/s/assign-json.0_0.hash +++ b/tests/integration/sandbox/det/s/assign-json.0_0.hash @@ -1 +1 @@ -41VMePfLyvKF2fm48mVduZoyE1Eh2B2Zi+7EzWDRwZg= +Ged0oYalGZldsnjjjCXLL5XGxaSD2wxod2rpJEJXjAg= diff --git a/tests/integration/sandbox/det/s/exit.0.hash b/tests/integration/sandbox/det/s/exit.0.hash index 045af958..dbf57fe2 100644 --- a/tests/integration/sandbox/det/s/exit.0.hash +++ b/tests/integration/sandbox/det/s/exit.0.hash @@ -1 +1 @@ -x3CBwGnyoVhBvq5/VvDraCJlPVBb5Jxdce6Ti8iU9gc= +g8wXDWJLYOFbRqofkeuXHbP5V9Wm8bT2R+sqF7tNwqM= diff --git a/tests/integration/sandbox/det/s/exit.0_0.hash b/tests/integration/sandbox/det/s/exit.0_0.hash index f076408f..a1eecdb5 100644 --- a/tests/integration/sandbox/det/s/exit.0_0.hash +++ b/tests/integration/sandbox/det/s/exit.0_0.hash @@ -1 +1 @@ -Ntq0ocfqM4abM3rlW6GTqnHMxzRGwXPHe0dzutu0D3A= +EjXoSauk9mibz2kNB6Ba+Y/P1oLPPgstcR4IHUt+W8Q= diff --git a/tests/integration/sandbox/det/s/print.0.hash b/tests/integration/sandbox/det/s/print.0.hash index 045af958..dbf57fe2 100644 --- a/tests/integration/sandbox/det/s/print.0.hash +++ b/tests/integration/sandbox/det/s/print.0.hash @@ -1 +1 @@ -x3CBwGnyoVhBvq5/VvDraCJlPVBb5Jxdce6Ti8iU9gc= +g8wXDWJLYOFbRqofkeuXHbP5V9Wm8bT2R+sqF7tNwqM= diff --git a/tests/integration/sandbox/det/s/print.0_0.hash b/tests/integration/sandbox/det/s/print.0_0.hash index 1f927ddd..d715e126 100644 --- a/tests/integration/sandbox/det/s/print.0_0.hash +++ b/tests/integration/sandbox/det/s/print.0_0.hash @@ -1 +1 @@ -E7UNivs2kF8lanfXUa+/TyPNnWQlIxfPggxwcl48t0I= +/t9f7FzZiyA1Nf4iSvxKTIDbto7/Y3vR4OEEFwun6Do= diff --git a/tests/integration/sandbox/det/s/rollback.0.hash b/tests/integration/sandbox/det/s/rollback.0.hash index 045af958..dbf57fe2 100644 --- a/tests/integration/sandbox/det/s/rollback.0.hash +++ b/tests/integration/sandbox/det/s/rollback.0.hash @@ -1 +1 @@ -x3CBwGnyoVhBvq5/VvDraCJlPVBb5Jxdce6Ti8iU9gc= +g8wXDWJLYOFbRqofkeuXHbP5V9Wm8bT2R+sqF7tNwqM= diff --git a/tests/integration/sandbox/det/s/rollback.0_0.hash b/tests/integration/sandbox/det/s/rollback.0_0.hash index 381e320c..5f83e9fe 100644 --- a/tests/integration/sandbox/det/s/rollback.0_0.hash +++ b/tests/integration/sandbox/det/s/rollback.0_0.hash @@ -1 +1 @@ -0xctr5uf7Xq0z88EBS+1DXS5aELNChftqxMgKMddrbE= +nAJFWoXybNQ8kpMkeR04o9qXCVBoFX5r5iUHj7M6Klo= diff --git a/tests/integration/sandbox/det/s/sandbox.0.hash b/tests/integration/sandbox/det/s/sandbox.0.hash index 045af958..dbf57fe2 100644 --- a/tests/integration/sandbox/det/s/sandbox.0.hash +++ b/tests/integration/sandbox/det/s/sandbox.0.hash @@ -1 +1 @@ -x3CBwGnyoVhBvq5/VvDraCJlPVBb5Jxdce6Ti8iU9gc= +g8wXDWJLYOFbRqofkeuXHbP5V9Wm8bT2R+sqF7tNwqM= diff --git a/tests/integration/sandbox/det/s/sandbox.0_0.hash b/tests/integration/sandbox/det/s/sandbox.0_0.hash index 214dd095..cb755f2a 100644 --- a/tests/integration/sandbox/det/s/sandbox.0_0.hash +++ b/tests/integration/sandbox/det/s/sandbox.0_0.hash @@ -1 +1 @@ -TMCIaqgc/lWwSZBUxS9+nLomzdOhEi8cQs1reJ7hY6Y= +ygSnWu/lNOrNScXeA8I0uoPXVbuOXd+yhG6rH0uiQsc= diff --git a/tests/integration/sandbox/det/sandbox_write.0.hash b/tests/integration/sandbox/det/sandbox_write.0.hash index 442e45c1..0283dc71 100644 --- a/tests/integration/sandbox/det/sandbox_write.0.hash +++ b/tests/integration/sandbox/det/sandbox_write.0.hash @@ -1 +1 @@ -9RQ0TdnNXFLlQGCkfJMJSMtJCOym9vjs5f4TfNZ4SEc= +lkKyR+6iRNOddTxjJpdn09JeG2bzYAnRGc4d7JlYe9I= diff --git a/tests/integration/sandbox/non-det/s/assign-json.0.hash b/tests/integration/sandbox/non-det/s/assign-json.0.hash index 3409e38c..a67132e6 100644 --- a/tests/integration/sandbox/non-det/s/assign-json.0.hash +++ b/tests/integration/sandbox/non-det/s/assign-json.0.hash @@ -1 +1 @@ -arV8ua+mzUevVgazJ4FiiTZOW+BSNeiheIx67m5V4MY= +gW+4X2ku+BdHzA9ZS2IQmYi0uVh5egkTpHxr+amzVFk= diff --git a/tests/integration/sandbox/non-det/s/assign-json.0_0.hash b/tests/integration/sandbox/non-det/s/assign-json.0_0.hash index 0f98385c..9c5974e6 100644 --- a/tests/integration/sandbox/non-det/s/assign-json.0_0.hash +++ b/tests/integration/sandbox/non-det/s/assign-json.0_0.hash @@ -1 +1 @@ -fdYOi8JhGU8A1pnyKCA9y58zoL8o3rsaCYSZjX4Phk0= +nw5qWOxCUQ22Fb2an5cPifkJcGU7ELHie3hiPQ+EU6s= diff --git a/tests/integration/sandbox/non-det/s/exit.0.hash b/tests/integration/sandbox/non-det/s/exit.0.hash index 3409e38c..a67132e6 100644 --- a/tests/integration/sandbox/non-det/s/exit.0.hash +++ b/tests/integration/sandbox/non-det/s/exit.0.hash @@ -1 +1 @@ -arV8ua+mzUevVgazJ4FiiTZOW+BSNeiheIx67m5V4MY= +gW+4X2ku+BdHzA9ZS2IQmYi0uVh5egkTpHxr+amzVFk= diff --git a/tests/integration/sandbox/non-det/s/exit.0_0.hash b/tests/integration/sandbox/non-det/s/exit.0_0.hash index 7046ac97..a1e825a8 100644 --- a/tests/integration/sandbox/non-det/s/exit.0_0.hash +++ b/tests/integration/sandbox/non-det/s/exit.0_0.hash @@ -1 +1 @@ -ky/k5tkVD2FE36CqNc8BOVK4NAXOgrifpU+uMDW2Wm8= +sW3ONR+G3OpvDcXBrsrgNOPhROMuKwmGuAunpL9pGlQ= diff --git a/tests/integration/sandbox/non-det/s/print.0.hash b/tests/integration/sandbox/non-det/s/print.0.hash index 3409e38c..a67132e6 100644 --- a/tests/integration/sandbox/non-det/s/print.0.hash +++ b/tests/integration/sandbox/non-det/s/print.0.hash @@ -1 +1 @@ -arV8ua+mzUevVgazJ4FiiTZOW+BSNeiheIx67m5V4MY= +gW+4X2ku+BdHzA9ZS2IQmYi0uVh5egkTpHxr+amzVFk= diff --git a/tests/integration/sandbox/non-det/s/print.0_0.hash b/tests/integration/sandbox/non-det/s/print.0_0.hash index 014c8f48..fab2a69b 100644 --- a/tests/integration/sandbox/non-det/s/print.0_0.hash +++ b/tests/integration/sandbox/non-det/s/print.0_0.hash @@ -1 +1 @@ -b47iFOhI/HE4eOpDgd8v9mM1gfYWkZWEQx0PPGkG4mg= +PtAzlM/Ne8EHyL4SR7Zoa4NJ7KZdmGcv18YQK1EeTzg= diff --git a/tests/integration/sandbox/non-det/s/rollback.0.hash b/tests/integration/sandbox/non-det/s/rollback.0.hash index 3409e38c..a67132e6 100644 --- a/tests/integration/sandbox/non-det/s/rollback.0.hash +++ b/tests/integration/sandbox/non-det/s/rollback.0.hash @@ -1 +1 @@ -arV8ua+mzUevVgazJ4FiiTZOW+BSNeiheIx67m5V4MY= +gW+4X2ku+BdHzA9ZS2IQmYi0uVh5egkTpHxr+amzVFk= diff --git a/tests/integration/sandbox/non-det/s/rollback.0_0.hash b/tests/integration/sandbox/non-det/s/rollback.0_0.hash index 6e22e4cc..6ab0de12 100644 --- a/tests/integration/sandbox/non-det/s/rollback.0_0.hash +++ b/tests/integration/sandbox/non-det/s/rollback.0_0.hash @@ -1 +1 @@ -YQ4ZsMP+nc9uQeYD3NNUkbh3WCz6E1U3skHcyMMQtd0= ++9Guv/0UQ14G7VYoIEVZmupyGVbMYpps5O8xxl5haQ0= diff --git a/tests/integration/sandbox/sandbox/sandbox.0.hash b/tests/integration/sandbox/sandbox/sandbox.0.hash index 3409e38c..a67132e6 100644 --- a/tests/integration/sandbox/sandbox/sandbox.0.hash +++ b/tests/integration/sandbox/sandbox/sandbox.0.hash @@ -1 +1 @@ -arV8ua+mzUevVgazJ4FiiTZOW+BSNeiheIx67m5V4MY= +gW+4X2ku+BdHzA9ZS2IQmYi0uVh5egkTpHxr+amzVFk= diff --git a/tests/integration/schema/complex_types/complex_types.0.hash b/tests/integration/schema/complex_types/complex_types.0.hash index 9939c435..c3644d17 100644 --- a/tests/integration/schema/complex_types/complex_types.0.hash +++ b/tests/integration/schema/complex_types/complex_types.0.hash @@ -1 +1 @@ -Gqn5G+Qn9L+fG+uIerLFjoyK5BclWLCdRcr0a5HKIM0= +Ghts8Gwo8yW55Y2WCwAbGLVY+Fp45hpTxgI4AbpTmX8= diff --git a/tests/integration/schema/complex_types/complex_types.0_0.hash b/tests/integration/schema/complex_types/complex_types.0_0.hash index c1b931e0..bacc613f 100644 --- a/tests/integration/schema/complex_types/complex_types.0_0.hash +++ b/tests/integration/schema/complex_types/complex_types.0_0.hash @@ -1 +1 @@ -Vu/U2VY/F8ZYciPgaGOR8IMeoOu2lqwOl+CysppA85o= +ztk2tFGlQQaty0DND2Geh5NXIuX1V/PCYEZjpX8YxeU= diff --git a/tests/integration/schema/prim_types/prim_types.0.hash b/tests/integration/schema/prim_types/prim_types.0.hash index 2f247b91..fe0f8f4e 100644 --- a/tests/integration/schema/prim_types/prim_types.0.hash +++ b/tests/integration/schema/prim_types/prim_types.0.hash @@ -1 +1 @@ -wYFtQxcTgDO3ChtT95Ik49JElzOwOKEOkHJWsu4WjPA= +t2NkNlsOyOp6EJ2AF/7oObirMEARxaFpI4KZ5q9yx7w= diff --git a/tests/integration/schema/prim_types/prim_types.0_0.hash b/tests/integration/schema/prim_types/prim_types.0_0.hash index e87d728f..0e1cd836 100644 --- a/tests/integration/schema/prim_types/prim_types.0_0.hash +++ b/tests/integration/schema/prim_types/prim_types.0_0.hash @@ -1 +1 @@ -VGZa98NQxLxiJox+7EP3JtctyMlVllxuyGQ5Qfo8pvU= +Tsm1akiSXkgZdlLbNXXj1sxzoTlr716ekcgLVvVBvXw= diff --git a/tests/integration/schema/pub_ctor/pub_ctor.0.hash b/tests/integration/schema/pub_ctor/pub_ctor.0.hash index e1b58aa7..612404da 100644 --- a/tests/integration/schema/pub_ctor/pub_ctor.0.hash +++ b/tests/integration/schema/pub_ctor/pub_ctor.0.hash @@ -1 +1 @@ -xdHD7v4ZTqyQgRflGZY4iyNkAHWQOqdPlimD2ALaKjY= +JcS2K1gWVhKKDQmqXoHV8ViKRZXEsGRucVKoK0aqFXI= diff --git a/tests/integration/schema/ret-float/ret-float.0.hash b/tests/integration/schema/ret-float/ret-float.0.hash index b74c2230..fe44b8b3 100644 --- a/tests/integration/schema/ret-float/ret-float.0.hash +++ b/tests/integration/schema/ret-float/ret-float.0.hash @@ -1 +1 @@ -9seCOwpLZ/J0UNizyDdBF1pZJPGemcj8KQr5oq21rfs= +fi1UVDnd14hmN83om3SMjse9nprCarBztSdjW8gXZQ8= diff --git a/tests/integration/schema/ret-float/ret-float.0_0.hash b/tests/integration/schema/ret-float/ret-float.0_0.hash index 06309608..1810b158 100644 --- a/tests/integration/schema/ret-float/ret-float.0_0.hash +++ b/tests/integration/schema/ret-float/ret-float.0_0.hash @@ -1 +1 @@ -dbesRtv+t0Kg3x0Z1H88q4vUUSrgGWCNjkHRg3iDcto= +qTEwWoaFWbebjTgAe0qidGx1zBehuDudWqtXbgDNs4k= diff --git a/tests/integration/schema/ret-tuple/ret-tuple.0.hash b/tests/integration/schema/ret-tuple/ret-tuple.0.hash index fbd46cd0..a6b99c92 100644 --- a/tests/integration/schema/ret-tuple/ret-tuple.0.hash +++ b/tests/integration/schema/ret-tuple/ret-tuple.0.hash @@ -1 +1 @@ -P3tTKqbOJGolmi2fSiD0Kb6M6TEI9jt/tzZVXZfetOQ= +94kmc1sD7/bBJCLnyk9+iUY9R9Ch54ERBIq8pyWV81M= diff --git a/tests/integration/schema/ret-tuple/ret-tuple.0_0.hash b/tests/integration/schema/ret-tuple/ret-tuple.0_0.hash index 98dbc13a..77d571b0 100644 --- a/tests/integration/schema/ret-tuple/ret-tuple.0_0.hash +++ b/tests/integration/schema/ret-tuple/ret-tuple.0_0.hash @@ -1 +1 @@ -oC4xgESUtUj7iSBLigVeuxXcj87lkK2ZpUhmK1GTvGE= +Bd5cBR4EKN90eY0REMArpGaSyMOosrkZq3g4VingST8= diff --git a/tests/integration/schema/returns/returns.0.hash b/tests/integration/schema/returns/returns.0.hash index 5ed1f889..af5e8328 100644 --- a/tests/integration/schema/returns/returns.0.hash +++ b/tests/integration/schema/returns/returns.0.hash @@ -1 +1 @@ -1ZdGLpQo2Hz+Sf8HzAC2eWUc73npGQnlcmfb/DZmnQw= +vYrICYyP28YNqGVSk1j0wrN3wwXCcG/jcanhd7IysS0= diff --git a/tests/integration/schema/returns/returns.0_0.hash b/tests/integration/schema/returns/returns.0_0.hash index 271b0a00..aea6eef6 100644 --- a/tests/integration/schema/returns/returns.0_0.hash +++ b/tests/integration/schema/returns/returns.0_0.hash @@ -1 +1 @@ -cI3tnkTHuq1kqgV1fe4MXij6lMZQgpwpXhWAhrBZq5s= +B1Yx+aIVhUsmp9Pmv/WmUF/niCF06YhPLCKswqW6x74= diff --git a/tests/integration/schema/returns/returns.0_1.hash b/tests/integration/schema/returns/returns.0_1.hash index 67b4053e..f4a3cd58 100644 --- a/tests/integration/schema/returns/returns.0_1.hash +++ b/tests/integration/schema/returns/returns.0_1.hash @@ -1 +1 @@ -X/AHPiTKT2Q8T/YvF4+ItCWV8UsFLpWMYoypE2TnsW8= +gMaqZOfGFB6is8bSJ1/aPhUyaGLSRVJadl7Bqqr094w= diff --git a/tests/integration/schema/returns/returns.0_2.hash b/tests/integration/schema/returns/returns.0_2.hash index 817bed0a..fd67f8f0 100644 --- a/tests/integration/schema/returns/returns.0_2.hash +++ b/tests/integration/schema/returns/returns.0_2.hash @@ -1 +1 @@ -NMlEEseBnhN2pV6yelall1F9P5fzQ+ommvZ9/yYaqTY= +KycDJoS9YtKQhXXeomkCodl7ueP4BreG8XWwSc+ntog= diff --git a/tests/integration/schema/returns/returns.0_3.hash b/tests/integration/schema/returns/returns.0_3.hash index 8b75c969..d3f31f7b 100644 --- a/tests/integration/schema/returns/returns.0_3.hash +++ b/tests/integration/schema/returns/returns.0_3.hash @@ -1 +1 @@ -G8SHHqDruNGauC6ckiKa1+JI0YMGJ5JsIdh0K7NwDTg= +uSCHWzi+6wFWW9PxjhPlTYGKnPXT8a81SUmJic7FAr4= diff --git a/tests/integration/schema/returns/returns.0_4.hash b/tests/integration/schema/returns/returns.0_4.hash index c909c9cd..a59f293b 100644 --- a/tests/integration/schema/returns/returns.0_4.hash +++ b/tests/integration/schema/returns/returns.0_4.hash @@ -1 +1 @@ -Se4bKNuDutnTS4HD52Sm34XVKEmR4HGyp8DQnHapGTw= +rxhJxR9NHRdd5zp220eCffTUYxtHA/f3kVADP4VL0kA= diff --git a/tests/integration/schema/returns/returns.0_5.hash b/tests/integration/schema/returns/returns.0_5.hash index bda8f9ce..83007432 100644 --- a/tests/integration/schema/returns/returns.0_5.hash +++ b/tests/integration/schema/returns/returns.0_5.hash @@ -1 +1 @@ -eDzXgFzBYJ0w0mpCLZkWTn1VkBDwgbD5/Ba5W3Hlnj8= +AqZ9hz9CDDSsb6rzFQsmC/DHousxgVWHuTZstN1uQok= diff --git a/tests/integration/schema/returns/returns.0_6.hash b/tests/integration/schema/returns/returns.0_6.hash index 2f62120b..1ad96132 100644 --- a/tests/integration/schema/returns/returns.0_6.hash +++ b/tests/integration/schema/returns/returns.0_6.hash @@ -1 +1 @@ -BVnigOF+gSvgIAdeRY0weimkS88PA+Bga4EMeSvKwHc= +mxd0LWsEyD3VmE//i3VyPJ6wwR6a3Hf2PofWgyMDlss= diff --git a/tests/integration/schema/returns/returns.0_7.hash b/tests/integration/schema/returns/returns.0_7.hash index 9461a32f..e2fa2d5f 100644 --- a/tests/integration/schema/returns/returns.0_7.hash +++ b/tests/integration/schema/returns/returns.0_7.hash @@ -1 +1 @@ -LhEB6m2W1VOygj1Wlm04o+dI9+CoXN5zH3Ko8hazp+o= +OPqKSJwn3XzyJbF8su12xdOKZKxBu3W+ZAFCkx04Uig= diff --git a/tests/integration/schema/returns/returns.0_8.hash b/tests/integration/schema/returns/returns.0_8.hash index bcc201b1..46597617 100644 --- a/tests/integration/schema/returns/returns.0_8.hash +++ b/tests/integration/schema/returns/returns.0_8.hash @@ -1 +1 @@ -SZR+MRRGGNxvv+jaartpk2+5sBUtclzDWA6LWAS+pyk= +7+Eig9TjFKVys2hbkp9H+AMN3IVjreZbz+7TGBtDbPU= diff --git a/tests/integration/schema/returns/returns.0_9.hash b/tests/integration/schema/returns/returns.0_9.hash index ecd840ba..8c572509 100644 --- a/tests/integration/schema/returns/returns.0_9.hash +++ b/tests/integration/schema/returns/returns.0_9.hash @@ -1 +1 @@ -RKp9ZIV79pAlOmZW5hARIkzBrgsTPHFegcqOGhzIAPM= +txqdHDuL6SUWTNOXQSUHC8J7L0cRmCO31Vpf9/77PaE= diff --git a/tests/integration/schema/schemas/ret.0.hash b/tests/integration/schema/schemas/ret.0.hash index c19e2feb..5e65d4a4 100644 --- a/tests/integration/schema/schemas/ret.0.hash +++ b/tests/integration/schema/schemas/ret.0.hash @@ -1 +1 @@ -UJcEKQZydbmd/mjitU6IO3WQBR/y74juxDncFFy7GyE= +FUf0an7NIa/STwoQzbDkIr7she+4GCYPLdoPzMpsjtQ= diff --git a/tests/integration/schema/schemas/ret.0_0.hash b/tests/integration/schema/schemas/ret.0_0.hash index a21a4c8b..64b62112 100644 --- a/tests/integration/schema/schemas/ret.0_0.hash +++ b/tests/integration/schema/schemas/ret.0_0.hash @@ -1 +1 @@ -lGhYyULF6S4qeyvZtMdef9ufqFGMc8o1cuDLnCdnKLs= +v/CyqUrAFS/6Fi/dgNK1/co50LY4GR1aY66ShkN/oFM= diff --git a/tests/integration/schema/schemas/trivial.0.hash b/tests/integration/schema/schemas/trivial.0.hash index c19e2feb..5e65d4a4 100644 --- a/tests/integration/schema/schemas/trivial.0.hash +++ b/tests/integration/schema/schemas/trivial.0.hash @@ -1 +1 @@ -UJcEKQZydbmd/mjitU6IO3WQBR/y74juxDncFFy7GyE= +FUf0an7NIa/STwoQzbDkIr7she+4GCYPLdoPzMpsjtQ= diff --git a/tests/integration/schema/schemas/trivial.0_0.hash b/tests/integration/schema/schemas/trivial.0_0.hash index a21a4c8b..64b62112 100644 --- a/tests/integration/schema/schemas/trivial.0_0.hash +++ b/tests/integration/schema/schemas/trivial.0_0.hash @@ -1 +1 @@ -lGhYyULF6S4qeyvZtMdef9ufqFGMc8o1cuDLnCdnKLs= +v/CyqUrAFS/6Fi/dgNK1/co50LY4GR1aY66ShkN/oFM= diff --git a/tests/integration/storage/alloc_generic/alloc_generic.0.hash b/tests/integration/storage/alloc_generic/alloc_generic.0.hash index 91cbd65d..8574e0e3 100644 --- a/tests/integration/storage/alloc_generic/alloc_generic.0.hash +++ b/tests/integration/storage/alloc_generic/alloc_generic.0.hash @@ -1 +1 @@ -fHxZLB1KCIYmFVEQatZf4NXMtZP71ZKYkvOcXLtZ+6U= +Ck0DW9cBjJ1BJPaQhWXCstNzgJ8z0gRcxOumsY4oS0A= diff --git a/tests/integration/storage/alloc_generic_err/alloc_generic_err.0.hash b/tests/integration/storage/alloc_generic_err/alloc_generic_err.0.hash index f4737c73..be2cc7f9 100644 --- a/tests/integration/storage/alloc_generic_err/alloc_generic_err.0.hash +++ b/tests/integration/storage/alloc_generic_err/alloc_generic_err.0.hash @@ -1 +1 @@ -8J0kbeqwqjzexQc05/TzqkOh+awyXRJKMWWxUtskoaA= +r1MVtTPzTpgEwLLycQDyJZLlirZN/qjMkd5uPgFjyFM= diff --git a/tests/integration/storage/base/base.0.hash b/tests/integration/storage/base/base.0.hash index a5b9a104..ce8611aa 100644 --- a/tests/integration/storage/base/base.0.hash +++ b/tests/integration/storage/base/base.0.hash @@ -1 +1 @@ -sDoBYnwd2d5xOdlVy1yoHapvfuAJVoRpf+0cbj/+C0s= +aYElMn4+A9Qc3ygB4/GLnwMnjd6PdUmka/wwpjvtcJQ= diff --git a/tests/integration/storage/bootstrapper/bootstrapper.0.hash b/tests/integration/storage/bootstrapper/bootstrapper.0.hash index 89bac9fc..9ec1ffe7 100644 --- a/tests/integration/storage/bootstrapper/bootstrapper.0.hash +++ b/tests/integration/storage/bootstrapper/bootstrapper.0.hash @@ -1 +1 @@ -bHp5Cw7n6xVZTxpXZ90QKI9QWOCkY5LMCf7JDDD/dIM= +31tOsgNymfI5lJNGZpsufagd5x7nWSMmHoO6LBN7XHE= diff --git a/tests/integration/storage/bootstrapper/bootstrapper.0_0.hash b/tests/integration/storage/bootstrapper/bootstrapper.0_0.hash index 520c2123..709293d8 100644 --- a/tests/integration/storage/bootstrapper/bootstrapper.0_0.hash +++ b/tests/integration/storage/bootstrapper/bootstrapper.0_0.hash @@ -1 +1 @@ -37dzXTgDVTV4BHAJOKgq5+ukkmdObZAw7gpnCFH9jlo= +lBhZpqaFLL3KvV8hdujO3r3PS+qxutIqGSOJKJzx3YM= diff --git a/tests/integration/storage/bootstrapper/bootstrapper.0_0_0.hash b/tests/integration/storage/bootstrapper/bootstrapper.0_0_0.hash index 57442a7d..ffb451b1 100644 --- a/tests/integration/storage/bootstrapper/bootstrapper.0_0_0.hash +++ b/tests/integration/storage/bootstrapper/bootstrapper.0_0_0.hash @@ -1 +1 @@ -rzseHXRlKCYTjZzpwPy+hbt24e9JbtR83Gd6yoFQvhw= +KLGDNLotOphVoyLQdfu8GXFm1ejQp/Kf2Oe0VX1UFzk= diff --git a/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0.hash b/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0.hash index 1326cba2..b2b4fdda 100644 --- a/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0.hash +++ b/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0.hash @@ -1 +1 @@ -dI8Um0bRXJaC+dbfYPkh2DsEcb5qs1rI2/5gJq12tSU= +rtmp40HdxTYbcLapsfled1m/BDdjwMhqAP+d8qu9p1o= diff --git a/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0_0.hash b/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0_0.hash index 42edec96..189d1d72 100644 --- a/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0_0.hash +++ b/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0_0.hash @@ -1 +1 @@ -drGVwvoLUMdK05wgcMPXpXE2jw09GDrUcvEwFlsjsvs= +lR3GVd0HCxqTwLPREBBB0N12qIHNwmcA6hJ3P8Utozo= diff --git a/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0_0_0.hash b/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0_0_0.hash index c2e04a0d..ad53f83c 100644 --- a/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0_0_0.hash +++ b/tests/integration/storage/bootstrapper/bootstrapper.0_0_0_0_0_0.hash @@ -1 +1 @@ -3cOLqwQVKcIPTPLh1dzTbqFK2DR1h7AV0eq1ssDVCV0= +r2xL90Og33i+vqrsRD4UuPH+HmQFIg+DegVHKcsnwrM= diff --git a/tests/integration/storage/floats/floats.0.hash b/tests/integration/storage/floats/floats.0.hash index d1dc475a..9f472620 100644 --- a/tests/integration/storage/floats/floats.0.hash +++ b/tests/integration/storage/floats/floats.0.hash @@ -1 +1 @@ -p89rW1u5zBQZLRSMaulCln+md5p17YU6E2MuqvyP40Q= +lseSbFGp629eot8Q66pKd+es4hL17yJBe2RY591o5XU= diff --git a/tests/integration/storage/gvm-89/gvm-89.0.hash b/tests/integration/storage/gvm-89/gvm-89.0.hash index b7274283..0d100396 100644 --- a/tests/integration/storage/gvm-89/gvm-89.0.hash +++ b/tests/integration/storage/gvm-89/gvm-89.0.hash @@ -1 +1 @@ -RZf2EEudGoyEmP31BVwJW9gu2vO4x4POcf/OorXGDjA= +x1AlIo2OIhEVEVFfh9J0mnrMGGVJOMiuvRi1BJvawCw= diff --git a/tests/integration/storage/gvm-89/gvm-89.0_0.hash b/tests/integration/storage/gvm-89/gvm-89.0_0.hash index 78e874b8..a9ea087d 100644 --- a/tests/integration/storage/gvm-89/gvm-89.0_0.hash +++ b/tests/integration/storage/gvm-89/gvm-89.0_0.hash @@ -1 +1 @@ -bMxdXrs5o3jCslQAl0MqJfWlK9xNhGoKK+tu1H5Pq8A= +5eRGaDBIEdDXgtfHXkpKDGq+buI7vl5cFkSALPawFN4= diff --git a/tests/integration/storage/hello_world_class/hello_world_class.0.hash b/tests/integration/storage/hello_world_class/hello_world_class.0.hash index 3db32032..52a7702b 100644 --- a/tests/integration/storage/hello_world_class/hello_world_class.0.hash +++ b/tests/integration/storage/hello_world_class/hello_world_class.0.hash @@ -1 +1 @@ -9RAYK7q7wLLVZz28eLs1APrzOvzcZY7s2ajd1q7MA64= +k9+dNEmHQRzba8qPatf82toKLqntOPW16q2yBbrn/Nc= diff --git a/tests/integration/storage/hello_world_class/hello_world_class.0_0.hash b/tests/integration/storage/hello_world_class/hello_world_class.0_0.hash index 5fc29075..b304df01 100644 --- a/tests/integration/storage/hello_world_class/hello_world_class.0_0.hash +++ b/tests/integration/storage/hello_world_class/hello_world_class.0_0.hash @@ -1 +1 @@ -A+KKAG1D5argOQMgxTeJJiuRegnchjX/DlwGveoL4vo= +2H0PRuzaific6ojWsMC1t087s/nZgfKpZLVXw0DoZuk= diff --git a/tests/integration/storage/locking/default-frozen.0.hash b/tests/integration/storage/locking/default-frozen.0.hash index d65b7da3..26bddc21 100644 --- a/tests/integration/storage/locking/default-frozen.0.hash +++ b/tests/integration/storage/locking/default-frozen.0.hash @@ -1 +1 @@ -VZxaO1xhE+5Kvs/K4+euWJ+83VWwafG12hVBJ4pacc4= +GzVFN5BorMvr/3XlmZGVgBFBDT7Dvh5NW8kDgcknccQ= diff --git a/tests/integration/storage/locking/default-frozen.0_0.hash b/tests/integration/storage/locking/default-frozen.0_0.hash index 0198e287..fdc8c47f 100644 --- a/tests/integration/storage/locking/default-frozen.0_0.hash +++ b/tests/integration/storage/locking/default-frozen.0_0.hash @@ -1 +1 @@ -fSZorSySoQcJOTOj8K7um7NcJFfiiJIp0GwsjCL6u8s= +NfjRQ2oJ1lXEUshcrj6BliVWrmjSEdvHIJ1vLRR4wT8= diff --git a/tests/integration/storage/locking/default-frozen.0_0_0.hash b/tests/integration/storage/locking/default-frozen.0_0_0.hash index 65efb587..5eef52f4 100644 --- a/tests/integration/storage/locking/default-frozen.0_0_0.hash +++ b/tests/integration/storage/locking/default-frozen.0_0_0.hash @@ -1 +1 @@ -8wOSZjalEv3kwooyrl2wH8wwSr+nFwzq0Si1AeNbYqo= +3n1a3dzylwevJ03KRx6ijKxsccxgY11ueQK3rzjSFWA= diff --git a/tests/integration/storage/locking/modify_ctor.0.hash b/tests/integration/storage/locking/modify_ctor.0.hash index d2207e4a..e49a0d92 100644 --- a/tests/integration/storage/locking/modify_ctor.0.hash +++ b/tests/integration/storage/locking/modify_ctor.0.hash @@ -1 +1 @@ -9bNN2MlteEm9VzOiYWPpmKucyiK1woUh2iQo4pQLiZw= +Lhl1Dm99uZ8zkZ5fDHIRgNDX2NbKLqRl3iEkCX50SDk= diff --git a/tests/integration/storage/locking/modify_ctor.0_0.hash b/tests/integration/storage/locking/modify_ctor.0_0.hash index e1a2f69c..6f5ad639 100644 --- a/tests/integration/storage/locking/modify_ctor.0_0.hash +++ b/tests/integration/storage/locking/modify_ctor.0_0.hash @@ -1 +1 @@ -1oCrFxyDC2DX38j8JQPp1SCWWsOavWTUx7vyplQEoBU= +S4UwCzpTRqj/1lirjUhs8umYuUc0IZfEBtegPGZ8yq0= diff --git a/tests/integration/storage/locking/modify_later.0.hash b/tests/integration/storage/locking/modify_later.0.hash index a58aa31a..fff40490 100644 --- a/tests/integration/storage/locking/modify_later.0.hash +++ b/tests/integration/storage/locking/modify_later.0.hash @@ -1 +1 @@ -BRm8+9tp6kSqd8619K0t23PQzfFbTsZGHFYPDzn8S74= +QWZLXg9QVW+JMULhaIq6bzl0uCCeFxuITKRFpwfli/E= diff --git a/tests/integration/storage/locking/modify_later.0_0.hash b/tests/integration/storage/locking/modify_later.0_0.hash index 2c240e59..1fe71186 100644 --- a/tests/integration/storage/locking/modify_later.0_0.hash +++ b/tests/integration/storage/locking/modify_later.0_0.hash @@ -1 +1 @@ -LyNEkduK8LsAc4FuWPg19yZNVmpgq4xqhCy9eQy1New= +l/ZcJgRU8P1gT3tavzJEm8FLAc1zq1s4Yxg+zITiCEg= diff --git a/tests/integration/storage/locking/modify_later.0_0_0.hash b/tests/integration/storage/locking/modify_later.0_0_0.hash index e1a2f69c..6f5ad639 100644 --- a/tests/integration/storage/locking/modify_later.0_0_0.hash +++ b/tests/integration/storage/locking/modify_later.0_0_0.hash @@ -1 +1 @@ -1oCrFxyDC2DX38j8JQPp1SCWWsOavWTUx7vyplQEoBU= +S4UwCzpTRqj/1lirjUhs8umYuUc0IZfEBtegPGZ8yq0= diff --git a/tests/integration/storage/np/np.0.hash b/tests/integration/storage/np/np.0.hash index 381d2bdd..38a46c10 100644 --- a/tests/integration/storage/np/np.0.hash +++ b/tests/integration/storage/np/np.0.hash @@ -1 +1 @@ -SbDxMIUpvjMfZIx+6JE0fRyRRjnZGEIrkcZPZI+9+pQ= +PWI+FyJ8zhy8DHm9d5FDoRnWeFuONnSFrwJQKPwJFi0= diff --git a/tests/integration/storage/persists/persists.0.hash b/tests/integration/storage/persists/persists.0.hash index edf86d9f..8e969237 100644 --- a/tests/integration/storage/persists/persists.0.hash +++ b/tests/integration/storage/persists/persists.0.hash @@ -1 +1 @@ -LEgTVOGyM/7QKZnxXbgONbK+T3zpK8tgeeA4mGHuPCo= +39jDIhM8WvezgyuJ1DmtVvuZvXY61LJp8sGnGNmxwA8= diff --git a/tests/integration/storage/persists/persists.0_0.hash b/tests/integration/storage/persists/persists.0_0.hash index be247f2e..232dcebb 100644 --- a/tests/integration/storage/persists/persists.0_0.hash +++ b/tests/integration/storage/persists/persists.0_0.hash @@ -1 +1 @@ -hTzsIZ+FKK+oMo/ilgHGRGuE0tw9EZ8UEkrC3gna8Oo= +tmdtrtJEACilGipMWpSkELMlewRPAWFo/VersfkWz0Q= diff --git a/tests/integration/storage/read_nondet/read_nondet.0.hash b/tests/integration/storage/read_nondet/read_nondet.0.hash index 3c921079..51ac11a9 100644 --- a/tests/integration/storage/read_nondet/read_nondet.0.hash +++ b/tests/integration/storage/read_nondet/read_nondet.0.hash @@ -1 +1 @@ -EPmDJqqZOAwO9T09xSuWcZeA/RYb7U+jasEo307hXp8= +ueHWTGR0YRjGrbVfrh0WwgcyXMdBooGsWaQvkp56xaE= diff --git a/tests/integration/storage/sandbox_fold_limit/sandbox_fold_limit.0.hash b/tests/integration/storage/sandbox_fold_limit/sandbox_fold_limit.0.hash index 2f1623b5..d11818de 100644 --- a/tests/integration/storage/sandbox_fold_limit/sandbox_fold_limit.0.hash +++ b/tests/integration/storage/sandbox_fold_limit/sandbox_fold_limit.0.hash @@ -1 +1 @@ -ACWH/oBG9vgmPB4E1HS/i4ymSIQxtosjkhBdZ+g9Oc8= +0AwSkLE6YWXnyoB4TMRvHkv2v3RdNp47aN09L4PudRk= diff --git a/tests/integration/storage/sandbox_fold_persists/sandbox_fold_persists.0.hash b/tests/integration/storage/sandbox_fold_persists/sandbox_fold_persists.0.hash index 7c427871..9441b55c 100644 --- a/tests/integration/storage/sandbox_fold_persists/sandbox_fold_persists.0.hash +++ b/tests/integration/storage/sandbox_fold_persists/sandbox_fold_persists.0.hash @@ -1 +1 @@ -mWSmBqKiJuyeC6CPPCxbHwrrJUGzfZuBK/mk0TEg60o= +PYx3pMfeQaxO5QV1XXeYKbnkisABMXlb6h/MaZPUQb8= diff --git a/tests/integration/storage/storage_tree_map/storage_tree_map.0.hash b/tests/integration/storage/storage_tree_map/storage_tree_map.0.hash index 5323eac6..deb73a3a 100644 --- a/tests/integration/storage/storage_tree_map/storage_tree_map.0.hash +++ b/tests/integration/storage/storage_tree_map/storage_tree_map.0.hash @@ -1 +1 @@ -pPZ/T+jNCORee5LNdJt/9kGxlmX/3EAwam5vEN4ABNk= +aWBOcBEWMaBDua+Qimy8f+OKXffLv7xQMu05lREv3L8= diff --git a/tests/integration/storage/store_proxy/store_proxy.0.hash b/tests/integration/storage/store_proxy/store_proxy.0.hash index 6e8653f1..1c8169d5 100644 --- a/tests/integration/storage/store_proxy/store_proxy.0.hash +++ b/tests/integration/storage/store_proxy/store_proxy.0.hash @@ -1 +1 @@ -GMMPylzP9OF79G7uuszzgVO4O8OnPkQ6OSt72ZVR6xI= +StBERbFNoia7zHPS97yelcvJsq+xRpctlI9VikZfzqk= diff --git a/tests/integration/storage/to_str/to_str.0.hash b/tests/integration/storage/to_str/to_str.0.hash index ba027c1b..37da4172 100644 --- a/tests/integration/storage/to_str/to_str.0.hash +++ b/tests/integration/storage/to_str/to_str.0.hash @@ -1 +1 @@ -PUqkxobuBKQNh9kROrtx+H/LiMN2a2fUgokJCSro5aQ= +RY6Gvw0jZxeotZ6znw3d7n/4FtVg7hmCde10lBIIE10= diff --git a/tests/integration/storage/tree_map_nested/tree_map_nested.0.hash b/tests/integration/storage/tree_map_nested/tree_map_nested.0.hash index a0d4d541..c553acbc 100644 --- a/tests/integration/storage/tree_map_nested/tree_map_nested.0.hash +++ b/tests/integration/storage/tree_map_nested/tree_map_nested.0.hash @@ -1 +1 @@ -khMqoG7zrSIz6gBac0yaVELGwaH+HH+Nk6NeBWmkMy8= +TqyvgF8RKZxlAOQokasAU1zL+CjUE6lbe58U+ImW6SU= diff --git a/tests/integration/storage/upgraders_overflow/upgraders_overflow.0.hash b/tests/integration/storage/upgraders_overflow/upgraders_overflow.0.hash index ae355573..ff6785aa 100644 --- a/tests/integration/storage/upgraders_overflow/upgraders_overflow.0.hash +++ b/tests/integration/storage/upgraders_overflow/upgraders_overflow.0.hash @@ -1 +1 @@ -eiN1WpYkYTwysNTh/RexGLOJLBjf+mnSxmyCXTNd5RQ= +j8xaHEBl/rdwlpIz1TCodLHyDpKlT+wJ6V7ya34twQw= diff --git a/tests/integration/storage/vecdb/vecdb.0.hash b/tests/integration/storage/vecdb/vecdb.0.hash index d20c3f88..2d94cb76 100644 --- a/tests/integration/storage/vecdb/vecdb.0.hash +++ b/tests/integration/storage/vecdb/vecdb.0.hash @@ -1 +1 @@ -nCqlgwxiHfTOut8f3jvbEyICDwhqHCbIq9Fjfnfoi9o= +fohMd3lZttYzHPPYY3jggSd313k/P9z9yAlgQWpXDOA= diff --git a/tests/integration/storage/woc/woc.0.hash b/tests/integration/storage/woc/woc.0.hash index e6ee1af5..5e0b4f35 100644 --- a/tests/integration/storage/woc/woc.0.hash +++ b/tests/integration/storage/woc/woc.0.hash @@ -1 +1 @@ -gXRJmMtIyBYzE8vL6Ed6dRBV0fzG5b4voEEZYtgFxrw= +FZYzsWfw0M6fNa1vaPusfMmqJxVgzIj8XW1Qplx2sew= diff --git a/tests/integration/storage/woc/woc.0_0.hash b/tests/integration/storage/woc/woc.0_0.hash index 0a46e377..dc88d835 100644 --- a/tests/integration/storage/woc/woc.0_0.hash +++ b/tests/integration/storage/woc/woc.0_0.hash @@ -1 +1 @@ -+ln5LX0b2k7JoCVuJfE1mGfEHT7By5D/8992eoI3tc4= +MxhGzMl6OIBCS96oQkO5aQOBK0yBoHZqv7mXUIcBK8U= diff --git a/tests/integration/storage/woc/woc.0_0_0_0.hash b/tests/integration/storage/woc/woc.0_0_0_0.hash index 0a46e377..dc88d835 100644 --- a/tests/integration/storage/woc/woc.0_0_0_0.hash +++ b/tests/integration/storage/woc/woc.0_0_0_0.hash @@ -1 +1 @@ -+ln5LX0b2k7JoCVuJfE1mGfEHT7By5D/8992eoI3tc4= +MxhGzMl6OIBCS96oQkO5aQOBK0yBoHZqv7mXUIcBK8U= diff --git a/tests/integration/storage/zero_fee_ram_bound/zero_fee_ram_bound.0.hash b/tests/integration/storage/zero_fee_ram_bound/zero_fee_ram_bound.0.hash index 26787d03..f0516b3f 100644 --- a/tests/integration/storage/zero_fee_ram_bound/zero_fee_ram_bound.0.hash +++ b/tests/integration/storage/zero_fee_ram_bound/zero_fee_ram_bound.0.hash @@ -1 +1 @@ -Zq0JVH2ftj2NqR6ovQ2YpQhiJfYSOrb6l4baA2mfflo= +IUBtY0gEKnJ4xarR8KdTiq0vryra9Lv5bUef3flqLkM= diff --git a/tests/integration/user-error/call_view/call_view.0.hash b/tests/integration/user-error/call_view/call_view.0.hash index bafcb3f2..5a679f3b 100644 --- a/tests/integration/user-error/call_view/call_view.0.hash +++ b/tests/integration/user-error/call_view/call_view.0.hash @@ -1 +1 @@ -t2gLEQhehAbOxGzC9idE9lSqORQ9tDMrBIv4tq94Df8= +80VAiJnLhKZDATRw08lDs/EtDOjamw61n7DHYDnYp/g= diff --git a/tests/integration/user-error/call_view/call_view.0_0.hash b/tests/integration/user-error/call_view/call_view.0_0.hash index 98a2e211..0619e31f 100644 --- a/tests/integration/user-error/call_view/call_view.0_0.hash +++ b/tests/integration/user-error/call_view/call_view.0_0.hash @@ -1 +1 @@ -rFjtaBarp5ettQuId5c8jM0acpxN2lgOon0T9XLz2bU= +zp5ueLgEqx49zyzP6Ky+ChxTCKNjiqzzkwhQHGGtU9E= diff --git a/tests/integration/user-error/call_view/call_view.0_0_0.hash b/tests/integration/user-error/call_view/call_view.0_0_0.hash index 0354697f..329b5a4b 100644 --- a/tests/integration/user-error/call_view/call_view.0_0_0.hash +++ b/tests/integration/user-error/call_view/call_view.0_0_0.hash @@ -1 +1 @@ -SFyV8CPi6vJLL4QnM7qxmbT+ZG3XWv4emPy0CdXqvrc= +nM56+RdKBRD7naH3WZC1SiYIasvyTd+8GbcBTtIo5A4= diff --git a/tests/integration/user-error/calldata_rollback/calldata_rollback.0.hash b/tests/integration/user-error/calldata_rollback/calldata_rollback.0.hash index a16e5ed8..201fbe9f 100644 --- a/tests/integration/user-error/calldata_rollback/calldata_rollback.0.hash +++ b/tests/integration/user-error/calldata_rollback/calldata_rollback.0.hash @@ -1 +1 @@ -MokepRa4RMcXmi8t9R8DPpqpq4iPxtOD0pd6M8t6LK4= +EGKm0GAabbm8oEQqYQkczC0gyzkhwy4XvSW5n75XipI= diff --git a/tests/integration/user-error/calldata_rollback/calldata_rollback.0_0.hash b/tests/integration/user-error/calldata_rollback/calldata_rollback.0_0.hash index 98a2e211..0619e31f 100644 --- a/tests/integration/user-error/calldata_rollback/calldata_rollback.0_0.hash +++ b/tests/integration/user-error/calldata_rollback/calldata_rollback.0_0.hash @@ -1 +1 @@ -rFjtaBarp5ettQuId5c8jM0acpxN2lgOon0T9XLz2bU= +zp5ueLgEqx49zyzP6Ky+ChxTCKNjiqzzkwhQHGGtU9E= diff --git a/tests/integration/user-error/calldata_rollback/calldata_rollback.0_0_0.hash b/tests/integration/user-error/calldata_rollback/calldata_rollback.0_0_0.hash index a0457584..bc674f8a 100644 --- a/tests/integration/user-error/calldata_rollback/calldata_rollback.0_0_0.hash +++ b/tests/integration/user-error/calldata_rollback/calldata_rollback.0_0_0.hash @@ -1 +1 @@ -cnq1BJKjdlTzhqpQOZZrzNiCQjOTIU5CH3aOVmrX6no= +3MZ/HBhNz+y10aVZ4U6nQXqGHEDvq7yxbSBwEdDLGWE= diff --git a/tests/integration/user-error/nondet/nondet.0.hash b/tests/integration/user-error/nondet/nondet.0.hash index 25a5d9bf..1c763a89 100644 --- a/tests/integration/user-error/nondet/nondet.0.hash +++ b/tests/integration/user-error/nondet/nondet.0.hash @@ -1 +1 @@ -oy0F+ugSwyUlZQkb9CMN1we93OBoJTEqem2JPJmbYXc= +r/wiJ16LHWmYZ0dhX2pkGyoZMnslvlHaxkEsfrk1T3s= diff --git a/tests/integration/user-error/simple/simple.0.hash b/tests/integration/user-error/simple/simple.0.hash index 24619ab5..e2b86973 100644 --- a/tests/integration/user-error/simple/simple.0.hash +++ b/tests/integration/user-error/simple/simple.0.hash @@ -1 +1 @@ -HKULWKB4S/KGUMD2Twdan6cUtLI/DPm7UTigg5bhtak= +ntLjecJYEcdqtuhtdLUbsuIhNVlg3eJSWCJnCUpIDjw= diff --git a/tests/integration/wasi/environ_args/environ_args.0.hash b/tests/integration/wasi/environ_args/environ_args.0.hash index 7b270f38..72a9a786 100644 --- a/tests/integration/wasi/environ_args/environ_args.0.hash +++ b/tests/integration/wasi/environ_args/environ_args.0.hash @@ -1 +1 @@ -dvDXk1xbFD5oKHEmZvr3r0/YFO9fr661g+1nXsoFzDo= +X7opSR8RxeDcMHhqadImnGkVZxjY0XQxhcyra/Jvl7M= diff --git a/tests/integration/wasi/wasi_clock/wasi_clock.0.hash b/tests/integration/wasi/wasi_clock/wasi_clock.0.hash index 469a98f0..b6ba85fe 100644 --- a/tests/integration/wasi/wasi_clock/wasi_clock.0.hash +++ b/tests/integration/wasi/wasi_clock/wasi_clock.0.hash @@ -1 +1 @@ -z59AKj3c8XtOXpVDrINL6SRwMFws5TUzDMo7Zn+pzhI= +98OjRECeuyIq9lx/DK5xL+dzBAZCQOUBQlo8iOrapZI= diff --git a/tests/integration/wasi/wasi_random/wasi_random.0.hash b/tests/integration/wasi/wasi_random/wasi_random.0.hash index 27285d61..fed370b5 100644 --- a/tests/integration/wasi/wasi_random/wasi_random.0.hash +++ b/tests/integration/wasi/wasi_random/wasi_random.0.hash @@ -1 +1 @@ -llHItxOxf6TVn7gABlSGLRJXqe850S/OXOZAw7z+ZxM= +d0NEyi02yD1c2ewvnrgOXa5pUFzn6NsWrPPv9jAYCBw= diff --git a/tests/integration/web/file_schema_web/file_schema_web_bash.0.hash b/tests/integration/web/file_schema_web/file_schema_web_bash.0.hash index b9e4c4ae..f5b7d746 100644 --- a/tests/integration/web/file_schema_web/file_schema_web_bash.0.hash +++ b/tests/integration/web/file_schema_web/file_schema_web_bash.0.hash @@ -1 +1 @@ -5pC7km2XNIvdOZ9c8tEzflM0FhQN4Mx6ZmbznbiCGS4= +uPvISn0ktp5c4j0vno8eklduyDJbXugmPg7ufZHgEtY= diff --git a/tests/integration/web/file_schema_web/file_schema_web_proc.0.hash b/tests/integration/web/file_schema_web/file_schema_web_proc.0.hash index e804ebf7..6f224c62 100644 --- a/tests/integration/web/file_schema_web/file_schema_web_proc.0.hash +++ b/tests/integration/web/file_schema_web/file_schema_web_proc.0.hash @@ -1 +1 @@ -HXPUTXyRQ3H5iQtJOSHIOjo5NzceUghddxX1m6Lt51I= +wwKy2YjTQIxJ2bPT/N+P/lfvRBajmLwk9g3V2wbndqM= diff --git a/tests/integration/web/get_webpage/get_webpage_html.0.hash b/tests/integration/web/get_webpage/get_webpage_html.0.hash index bd0475de..79cd7981 100644 --- a/tests/integration/web/get_webpage/get_webpage_html.0.hash +++ b/tests/integration/web/get_webpage/get_webpage_html.0.hash @@ -1 +1 @@ -ttubOTGf9F2IcO2ueiBzAwS6bipGky3RJjmT+yD1hI4= +gjIxUsyewVM8iatpBXdHvwOywQnTQaxfxON/Kted6MA= diff --git a/tests/integration/web/get_webpage/get_webpage_text.0.hash b/tests/integration/web/get_webpage/get_webpage_text.0.hash index bd0475de..79cd7981 100644 --- a/tests/integration/web/get_webpage/get_webpage_text.0.hash +++ b/tests/integration/web/get_webpage/get_webpage_text.0.hash @@ -1 +1 @@ -ttubOTGf9F2IcO2ueiBzAwS6bipGky3RJjmT+yD1hI4= +gjIxUsyewVM8iatpBXdHvwOywQnTQaxfxON/Kted6MA= diff --git a/tests/integration/web/request_signed/request_signed.0.hash b/tests/integration/web/request_signed/request_signed.0.hash index 51ac26b2..aa60f079 100644 --- a/tests/integration/web/request_signed/request_signed.0.hash +++ b/tests/integration/web/request_signed/request_signed.0.hash @@ -1 +1 @@ -Dgh15JYOMTsD98sS/veNkbAueYAEYXKcR53NMu/v0PE= +fzAO/P29/FIpPbb9x2Wf9gOR7KUBxWiCUl2UNqEpVZc=