diff --git a/examples/amm/src/contract.rs b/examples/amm/src/contract.rs index 55d4d11ce1c7..21fb02dfe5b2 100644 --- a/examples/amm/src/contract.rs +++ b/examples/amm/src/contract.rs @@ -55,7 +55,12 @@ impl Contract for AmmContract { } } - async fn execute_message(&mut self, message: Self::Message) { + async fn execute_message( + &mut self, + _is_bouncing: bool, + origin: ChainId, + message: Self::Message, + ) { assert_eq!( self.runtime.chain_id(), self.runtime.application_creator_chain_id(), @@ -93,7 +98,10 @@ impl Contract for AmmContract { self.transfer(owner, input_amount, amm_account, input_token_idx); let amm_app_owner = self.get_amm_app_owner(); - let message_origin_account = self.get_message_origin_account(owner); + let message_origin_account = Account { + chain_id: origin, + owner, + }; self.transfer( amm_app_owner, output_amount, @@ -180,7 +188,10 @@ impl Contract for AmmContract { } let amm_account = self.get_amm_account(); - let message_origin_account = self.get_message_origin_account(owner); + let message_origin_account = Account { + chain_id: origin, + owner, + }; // See if we'll need to send refunds if token0_amount < max_token0_amount { self.transfer( @@ -272,7 +283,10 @@ impl Contract for AmmContract { self.get_shares(other_amount, token_to_remove_amount, &balance0_bigint) }; - let message_origin_account = self.get_message_origin_account(owner); + let message_origin_account = Account { + chain_id: origin, + owner, + }; let current_shares = self .current_shares_or_default(&message_origin_account) .await; @@ -295,7 +309,10 @@ impl Contract for AmmContract { .check_account_permission(owner) .expect("Permission for RemoveAllAddedLiquidity message"); - let message_origin_account = self.get_message_origin_account(owner); + let message_origin_account = Account { + chain_id: origin, + owner, + }; let current_shares = self .current_shares_or_default(&message_origin_account) .await; @@ -444,16 +461,6 @@ impl AmmContract { } } - fn get_message_origin_account(&mut self, owner: AccountOwner) -> Account { - Account { - chain_id: self - .runtime - .message_origin_chain_id() - .expect("Getting message origin chain ID should not fail"), - owner, - } - } - fn get_account_on_amm_chain(&mut self, owner: AccountOwner) -> Account { Account { chain_id: self.get_amm_chain_id(), diff --git a/examples/call-evm-counter/src/contract.rs b/examples/call-evm-counter/src/contract.rs index 1c6ae84f4c77..d5819bc91d9c 100644 --- a/examples/call-evm-counter/src/contract.rs +++ b/examples/call-evm-counter/src/contract.rs @@ -9,7 +9,7 @@ use call_evm_counter::{CallCounterAbi, CallCounterOperation}; use linera_sdk::{ abis::evm::EvmAbi, linera_base_types::{ApplicationId, WithContractAbi}, - Contract, ContractRuntime, + ChainId, Contract, ContractRuntime, }; pub struct CallCounterContract { @@ -68,7 +68,7 @@ impl Contract for CallCounterContract { } } - async fn execute_message(&mut self, _message: ()) { + async fn execute_message(&mut self, _is_bouncing: bool, _origin: ChainId, _message: ()) { panic!("Counter application doesn't support any cross-chain messages"); } diff --git a/examples/counter-no-graphql/src/contract.rs b/examples/counter-no-graphql/src/contract.rs index 39ebe49e10c7..e14d16136d7e 100644 --- a/examples/counter-no-graphql/src/contract.rs +++ b/examples/counter-no-graphql/src/contract.rs @@ -9,7 +9,7 @@ use counter_no_graphql::{CounterNoGraphQlAbi, CounterOperation}; use linera_sdk::{ linera_base_types::WithContractAbi, views::{RootView, View}, - Contract, ContractRuntime, + ChainId, Contract, ContractRuntime, }; use self::state::CounterState; @@ -53,7 +53,7 @@ impl Contract for CounterContract { new_value } - async fn execute_message(&mut self, _message: ()) { + async fn execute_message(&mut self, _is_bouncing: bool, _chain_id: ChainId, _message: ()) { panic!("Counter application doesn't support any cross-chain messages"); } @@ -94,8 +94,9 @@ mod tests { let initial_value = 72_u64; let mut counter = create_and_instantiate_counter(initial_value); + use linera_sdk::linera_base_types::ChainId; counter - .execute_message(()) + .execute_message(false, ChainId::default(), ()) .now_or_never() .expect("Execution of counter operation should not await anything"); } diff --git a/examples/counter/src/contract.rs b/examples/counter/src/contract.rs index 1063f7689988..80a9275fec66 100644 --- a/examples/counter/src/contract.rs +++ b/examples/counter/src/contract.rs @@ -9,7 +9,7 @@ use counter::CounterAbi; use linera_sdk::{ linera_base_types::WithContractAbi, views::{RootView, View}, - Contract, ContractRuntime, + ChainId, Contract, ContractRuntime, }; use self::state::CounterState; @@ -51,7 +51,7 @@ impl Contract for CounterContract { new_value } - async fn execute_message(&mut self, _message: ()) { + async fn execute_message(&mut self, _is_bouncing: bool, _origin: ChainId, _message: ()) { panic!("Counter application doesn't support any cross-chain messages"); } @@ -63,7 +63,7 @@ impl Contract for CounterContract { #[cfg(test)] mod tests { use futures::FutureExt as _; - use linera_sdk::{util::BlockingWait, views::View, Contract, ContractRuntime}; + use linera_sdk::{util::BlockingWait, views::View, ChainId, Contract, ContractRuntime}; use super::{CounterContract, CounterState}; @@ -92,7 +92,7 @@ mod tests { let mut counter = create_and_instantiate_counter(initial_value); counter - .execute_message(()) + .execute_message(false, ChainId::default(), ()) .now_or_never() .expect("Execution of counter operation should not await anything"); } diff --git a/examples/create-and-call/src/contract.rs b/examples/create-and-call/src/contract.rs index add8196b3ae9..bdc949357948 100644 --- a/examples/create-and-call/src/contract.rs +++ b/examples/create-and-call/src/contract.rs @@ -10,7 +10,7 @@ use create_and_call::{CreateAndCallAbi, CreateAndCallOperation}; use linera_sdk::{ linera_base_types::{Bytecode, VmRuntime, WithContractAbi}, views::{RootView, View}, - Contract, ContractRuntime, + ChainId, Contract, ContractRuntime, }; use self::state::CreateAndCallState; @@ -84,7 +84,7 @@ impl Contract for CreateAndCallContract { .call_application(true, application_id, &counter_operation) } - async fn execute_message(&mut self, _message: ()) { + async fn execute_message(&mut self, _is_bouncing: bool, _origin: ChainId, _message: ()) { panic!("Create and call application doesn't support any cross-chain messages"); } diff --git a/examples/crowd-funding/src/contract.rs b/examples/crowd-funding/src/contract.rs index 44506f3fc56f..0503463e4961 100644 --- a/examples/crowd-funding/src/contract.rs +++ b/examples/crowd-funding/src/contract.rs @@ -11,7 +11,7 @@ use linera_sdk::{ abis::fungible::FungibleOperation, linera_base_types::{AccountOwner, Amount, ApplicationId, WithContractAbi}, views::{RootView, View}, - Contract, ContractRuntime, + ChainId, Contract, ContractRuntime, }; use state::{CrowdFundingState, Status}; @@ -66,7 +66,7 @@ impl Contract for CrowdFundingContract { } } - async fn execute_message(&mut self, message: Message) { + async fn execute_message(&mut self, _is_bouncing: bool, _origin: ChainId, message: Message) { match message { Message::PledgeWithAccount { owner, amount } => { assert_eq!( diff --git a/examples/ethereum-tracker/src/contract.rs b/examples/ethereum-tracker/src/contract.rs index 151720c297d5..bbfcbe643257 100644 --- a/examples/ethereum-tracker/src/contract.rs +++ b/examples/ethereum-tracker/src/contract.rs @@ -10,7 +10,7 @@ use ethereum_tracker::{EthereumTrackerAbi, InstantiationArgument}; use linera_sdk::{ linera_base_types::WithContractAbi, views::{RootView, View}, - Contract, ContractRuntime, + ChainId, Contract, ContractRuntime, }; use self::state::EthereumTrackerState; @@ -66,7 +66,7 @@ impl Contract for EthereumTrackerContract { } } - async fn execute_message(&mut self, _message: ()) { + async fn execute_message(&mut self, _is_bouncing: bool, _origin: ChainId, _message: ()) { panic!("Messages not supported"); } diff --git a/examples/fungible/src/contract.rs b/examples/fungible/src/contract.rs index d0baea1ea0e3..720e5e75ab45 100644 --- a/examples/fungible/src/contract.rs +++ b/examples/fungible/src/contract.rs @@ -12,7 +12,7 @@ use fungible::{ use linera_sdk::{ linera_base_types::{AccountOwner, Amount, WithContractAbi}, views::{RootView, View}, - Contract, ContractRuntime, + ChainId, Contract, ContractRuntime, }; use self::state::FungibleTokenState; @@ -124,17 +124,13 @@ impl Contract for FungibleTokenContract { } } - async fn execute_message(&mut self, message: Message) { + async fn execute_message(&mut self, is_bouncing: bool, _chain_id: ChainId, message: Message) { match message { Message::Credit { amount, target, source, } => { - let is_bouncing = self - .runtime - .message_is_bouncing() - .expect("Message delivery status has to be available when executing a message"); let receiver = if is_bouncing { source } else { target }; self.state.credit(receiver, amount).await; } diff --git a/examples/gen-nft/src/contract.rs b/examples/gen-nft/src/contract.rs index b2a10bfc3a14..940cdfb0b4e0 100644 --- a/examples/gen-nft/src/contract.rs +++ b/examples/gen-nft/src/contract.rs @@ -12,7 +12,7 @@ use gen_nft::{GenNftAbi, Message, Nft, Operation, TokenId}; use linera_sdk::{ linera_base_types::{AccountOwner, WithContractAbi}, views::{RootView, View}, - Contract, ContractRuntime, + ChainId, Contract, ContractRuntime, }; use self::state::GenNftState; @@ -91,16 +91,12 @@ impl Contract for GenNftContract { } } - async fn execute_message(&mut self, message: Message) { + async fn execute_message(&mut self, is_bouncing: bool, _origin: ChainId, message: Message) { match message { Message::Transfer { mut nft, target_account, } => { - let is_bouncing = self - .runtime - .message_is_bouncing() - .expect("Message delivery status has to be available when executing a message"); if !is_bouncing { nft.owner = target_account.owner; } diff --git a/examples/hex-game/src/contract.rs b/examples/hex-game/src/contract.rs index 303171b31931..c184dfff1c47 100644 --- a/examples/hex-game/src/contract.rs +++ b/examples/hex-game/src/contract.rs @@ -66,7 +66,7 @@ impl Contract for HexContract { self.handle_winner(outcome) } - async fn execute_message(&mut self, message: Message) { + async fn execute_message(&mut self, _is_bouncing: bool, origin: ChainId, message: Message) { log::trace!("Handling message {:?}", message); match message { Message::Start { @@ -80,7 +80,6 @@ impl Contract for HexContract { self.state.board.set(Board::new(board_size)); } Message::End { winner, loser } => { - let origin_chain_id = self.runtime.message_origin_chain_id().unwrap(); for owner in [&winner, &loser] { let chain_set = self .state @@ -88,7 +87,7 @@ impl Contract for HexContract { .get_mut_or_default(owner) .await .unwrap(); - chain_set.retain(|game_chain| game_chain.chain_id != origin_chain_id); + chain_set.retain(|game_chain| game_chain.chain_id != origin); if chain_set.is_empty() { self.state.game_chains.remove(owner).unwrap(); } diff --git a/examples/how-to/perform-http-requests/src/contract.rs b/examples/how-to/perform-http-requests/src/contract.rs index e62323cfd69d..5cf82ec37a76 100644 --- a/examples/how-to/perform-http-requests/src/contract.rs +++ b/examples/how-to/perform-http-requests/src/contract.rs @@ -4,7 +4,9 @@ #![cfg_attr(target_arch = "wasm32", no_main)] use how_to_perform_http_requests::{Abi, Operation}; -use linera_sdk::{http, linera_base_types::WithContractAbi, Contract as _, ContractRuntime}; +use linera_sdk::{ + http, linera_base_types::WithContractAbi, ChainId, Contract as _, ContractRuntime, +}; pub struct Contract { runtime: ContractRuntime, @@ -41,7 +43,7 @@ impl linera_sdk::Contract for Contract { } } - async fn execute_message(&mut self, (): Self::Message) { + async fn execute_message(&mut self, _is_bouncing: bool, _origin: ChainId, (): Self::Message) { panic!("This application doesn't support any cross-chain messages"); } diff --git a/examples/llm/src/contract.rs b/examples/llm/src/contract.rs index 6388358e80c8..98355566740c 100644 --- a/examples/llm/src/contract.rs +++ b/examples/llm/src/contract.rs @@ -3,7 +3,7 @@ #![cfg_attr(target_arch = "wasm32", no_main)] -use linera_sdk::{linera_base_types::WithContractAbi, Contract, ContractRuntime}; +use linera_sdk::{linera_base_types::WithContractAbi, ChainId, Contract, ContractRuntime}; pub struct LlmContract; @@ -27,7 +27,7 @@ impl Contract for LlmContract { async fn execute_operation(&mut self, _operation: ()) -> Self::Response {} - async fn execute_message(&mut self, _message: ()) { + async fn execute_message(&mut self, _is_bouncing: bool, _chain_id: ChainId, _message: ()) { panic!("Llm application doesn't support any cross-chain messages"); } diff --git a/examples/matching-engine/src/contract.rs b/examples/matching-engine/src/contract.rs index 8a79af558f5a..ca09b5d58d19 100644 --- a/examples/matching-engine/src/contract.rs +++ b/examples/matching-engine/src/contract.rs @@ -109,7 +109,7 @@ impl Contract for MatchingEngineContract { } /// Execution of the order on the creation chain - async fn execute_message(&mut self, message: Message) { + async fn execute_message(&mut self, _is_bouncing: bool, origin: ChainId, message: Message) { assert_eq!( self.runtime.chain_id(), self.runtime.application_creator_chain_id(), @@ -118,13 +118,10 @@ impl Contract for MatchingEngineContract { match message { Message::ExecuteOrder { order } => { let owner = Self::get_owner(&order); - let origin_chain_id = self.runtime.message_origin_chain_id().expect( - "Incoming message origin chain ID has to be available when executing a message", - ); self.runtime .check_account_permission(owner) .expect("Permission for ExecuteOrder message"); - self.execute_order_local(order, origin_chain_id).await; + self.execute_order_local(order, origin).await; } } } diff --git a/examples/meta-counter/src/contract.rs b/examples/meta-counter/src/contract.rs index 9fc2198e15af..ff7b865f9b58 100644 --- a/examples/meta-counter/src/contract.rs +++ b/examples/meta-counter/src/contract.rs @@ -5,7 +5,7 @@ use linera_sdk::{ linera_base_types::{ApplicationId, StreamName, WithContractAbi}, - Contract, ContractRuntime, Resources, + ChainId, Contract, ContractRuntime, Resources, }; use meta_counter::{Message, MetaCounterAbi, Operation}; @@ -79,11 +79,7 @@ impl Contract for MetaCounterContract { message.send_to(recipient_id); } - async fn execute_message(&mut self, message: Message) { - let is_bouncing = self - .runtime - .message_is_bouncing() - .expect("Message delivery status has to be available when executing a message"); + async fn execute_message(&mut self, is_bouncing: bool, _chain_id: ChainId, message: Message) { if is_bouncing { log::trace!("receiving a bouncing message {message:?}"); return; diff --git a/examples/native-fungible/src/contract.rs b/examples/native-fungible/src/contract.rs index 2eb47f2920eb..9843358dcd85 100644 --- a/examples/native-fungible/src/contract.rs +++ b/examples/native-fungible/src/contract.rs @@ -101,7 +101,12 @@ impl Contract for NativeFungibleTokenContract { } } - async fn execute_message(&mut self, message: Self::Message) { + async fn execute_message( + &mut self, + _is_bouncing: bool, + _origin: ChainId, + message: Self::Message, + ) { // Messages for now don't do anything, just pass messages around match message { Message::Notify => (), diff --git a/examples/non-fungible/src/contract.rs b/examples/non-fungible/src/contract.rs index 3a141cfdb4ff..124d8e3efab5 100644 --- a/examples/non-fungible/src/contract.rs +++ b/examples/non-fungible/src/contract.rs @@ -11,7 +11,7 @@ use fungible::Account; use linera_sdk::{ linera_base_types::{AccountOwner, WithContractAbi}, views::{RootView, View}, - Contract, ContractRuntime, DataBlobHash, + ChainId, Contract, ContractRuntime, DataBlobHash, }; use non_fungible::{Message, Nft, NonFungibleTokenAbi, Operation, TokenId}; @@ -96,16 +96,12 @@ impl Contract for NonFungibleTokenContract { } } - async fn execute_message(&mut self, message: Message) { + async fn execute_message(&mut self, is_bouncing: bool, _origin: ChainId, message: Message) { match message { Message::Transfer { mut nft, target_account, } => { - let is_bouncing = self - .runtime - .message_is_bouncing() - .expect("Message delivery status has to be available when executing a message"); if !is_bouncing { nft.owner = target_account.owner; } diff --git a/examples/rfq/src/contract.rs b/examples/rfq/src/contract.rs index 4e5bc1df4ddc..4fb5ee793253 100644 --- a/examples/rfq/src/contract.rs +++ b/examples/rfq/src/contract.rs @@ -190,11 +190,12 @@ impl Contract for RfqContract { } } - async fn execute_message(&mut self, message: Self::Message) { - let origin_chain_id = self - .runtime - .message_origin_chain_id() - .expect("Getting message origin chain ID should not fail"); + async fn execute_message( + &mut self, + _is_bouncing: bool, + origin_chain_id: ChainId, + message: Self::Message, + ) { let request_id = message.request_id(origin_chain_id); match message { Message::RequestQuote { diff --git a/examples/social/src/contract.rs b/examples/social/src/contract.rs index c7c1841867ef..ad53a3b5e70b 100644 --- a/examples/social/src/contract.rs +++ b/examples/social/src/contract.rs @@ -68,7 +68,7 @@ impl Contract for SocialContract { } } - async fn execute_message(&mut self, message: Message) { + async fn execute_message(&mut self, _is_bouncing: bool, _origin: ChainId, message: Message) { match message { Message::Like { key } => self.runtime.emit(STREAM_NAME.into(), &Event::Like { key }), diff --git a/linera-execution/solidity/Linera.sol b/linera-execution/solidity/Linera.sol index 96026c44d323..ebd4910f8780 100644 --- a/linera-execution/solidity/Linera.sol +++ b/linera-execution/solidity/Linera.sol @@ -225,24 +225,6 @@ library Linera { return opt_ChainId(false, ChainId(bytes32(0))); } - enum OptionBool { None, True, False } - - function optionbool_from(LineraTypes.MessageIsBouncing memory entry) - internal - pure - returns (OptionBool) - { - if (entry.value == LineraTypes.OptionBool.True) { - return OptionBool.True; - } - if (entry.value == LineraTypes.OptionBool.False) { - return OptionBool.False; - } - return OptionBool.None; - } - - - struct StreamUpdate { ChainId chain_id; StreamId stream_id; @@ -415,27 +397,6 @@ library Linera { return opt_accountowner_from(output2); } - function message_origin_chain_id() internal returns (opt_ChainId memory) { - address precompile = address(0x0b); - LineraTypes.ContractRuntimePrecompile memory contract_ = LineraTypes.ContractRuntimePrecompile_case_message_origin_chain_id(); - LineraTypes.RuntimePrecompile memory input1 = LineraTypes.RuntimePrecompile_case_contract(contract_); - bytes memory input2 = LineraTypes.bcs_serialize_RuntimePrecompile(input1); - (bool success, bytes memory output1) = precompile.call(input2); - require(success); - LineraTypes.opt_ChainId memory output2 = LineraTypes.bcs_deserialize_opt_ChainId(output1); - return opt_chainid_from(output2); - } - - function message_is_bouncing() internal returns (OptionBool) { - address precompile = address(0x0b); - LineraTypes.ContractRuntimePrecompile memory contract_ = LineraTypes.ContractRuntimePrecompile_case_message_is_bouncing(); - LineraTypes.RuntimePrecompile memory input1 = LineraTypes.RuntimePrecompile_case_contract(contract_); - bytes memory input2 = LineraTypes.bcs_serialize_RuntimePrecompile(input1); - (bool success, bytes memory output1) = precompile.call(input2); - require(success); - LineraTypes.MessageIsBouncing memory output2 = LineraTypes.bcs_deserialize_MessageIsBouncing(output1); - return optionbool_from(output2); - } function authenticated_caller_id() internal returns (Linera.opt_ApplicationId memory) { address precompile = address(0x0b); diff --git a/linera-execution/solidity/LineraTypes.sol b/linera-execution/solidity/LineraTypes.sol index 9f33e66fdd18..757a2cbc27a1 100644 --- a/linera-execution/solidity/LineraTypes.sol +++ b/linera-execution/solidity/LineraTypes.sol @@ -566,24 +566,22 @@ library LineraTypes { struct ContractRuntimePrecompile { uint8 choice; // choice=0 corresponds to AuthenticatedSigner - // choice=1 corresponds to MessageOriginChainId - // choice=2 corresponds to MessageIsBouncing - // choice=3 corresponds to AuthenticatedCallerId - // choice=4 corresponds to SendMessage + // choice=1 corresponds to AuthenticatedCallerId + // choice=2 corresponds to SendMessage ContractRuntimePrecompile_SendMessage send_message; - // choice=5 corresponds to TryCallApplication + // choice=3 corresponds to TryCallApplication ContractRuntimePrecompile_TryCallApplication try_call_application; - // choice=6 corresponds to Emit + // choice=4 corresponds to Emit ContractRuntimePrecompile_Emit emit_; - // choice=7 corresponds to ReadEvent + // choice=5 corresponds to ReadEvent ContractRuntimePrecompile_ReadEvent read_event; - // choice=8 corresponds to SubscribeToEvents + // choice=6 corresponds to SubscribeToEvents ContractRuntimePrecompile_SubscribeToEvents subscribe_to_events; - // choice=9 corresponds to UnsubscribeFromEvents + // choice=7 corresponds to UnsubscribeFromEvents ContractRuntimePrecompile_UnsubscribeFromEvents unsubscribe_from_events; - // choice=10 corresponds to QueryService + // choice=8 corresponds to QueryService ContractRuntimePrecompile_QueryService query_service; - // choice=11 corresponds to ValidationRound + // choice=9 corresponds to ValidationRound } function ContractRuntimePrecompile_case_authenticated_signer() @@ -601,36 +599,6 @@ library LineraTypes { return ContractRuntimePrecompile(uint8(0), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); } - function ContractRuntimePrecompile_case_message_origin_chain_id() - internal - pure - returns (ContractRuntimePrecompile memory) - { - ContractRuntimePrecompile_SendMessage memory send_message; - ContractRuntimePrecompile_TryCallApplication memory try_call_application; - ContractRuntimePrecompile_Emit memory emit_; - ContractRuntimePrecompile_ReadEvent memory read_event; - ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; - ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; - ContractRuntimePrecompile_QueryService memory query_service; - return ContractRuntimePrecompile(uint8(1), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); - } - - function ContractRuntimePrecompile_case_message_is_bouncing() - internal - pure - returns (ContractRuntimePrecompile memory) - { - ContractRuntimePrecompile_SendMessage memory send_message; - ContractRuntimePrecompile_TryCallApplication memory try_call_application; - ContractRuntimePrecompile_Emit memory emit_; - ContractRuntimePrecompile_ReadEvent memory read_event; - ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; - ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; - ContractRuntimePrecompile_QueryService memory query_service; - return ContractRuntimePrecompile(uint8(2), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); - } - function ContractRuntimePrecompile_case_authenticated_caller_id() internal pure @@ -643,7 +611,7 @@ library LineraTypes { ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; ContractRuntimePrecompile_QueryService memory query_service; - return ContractRuntimePrecompile(uint8(3), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); + return ContractRuntimePrecompile(uint8(1), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); } function ContractRuntimePrecompile_case_send_message(ContractRuntimePrecompile_SendMessage memory send_message) @@ -657,7 +625,7 @@ library LineraTypes { ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; ContractRuntimePrecompile_QueryService memory query_service; - return ContractRuntimePrecompile(uint8(4), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); + return ContractRuntimePrecompile(uint8(2), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); } function ContractRuntimePrecompile_case_try_call_application(ContractRuntimePrecompile_TryCallApplication memory try_call_application) @@ -671,7 +639,7 @@ library LineraTypes { ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; ContractRuntimePrecompile_QueryService memory query_service; - return ContractRuntimePrecompile(uint8(5), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); + return ContractRuntimePrecompile(uint8(3), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); } function ContractRuntimePrecompile_case_emit(ContractRuntimePrecompile_Emit memory emit_) @@ -685,7 +653,7 @@ library LineraTypes { ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; ContractRuntimePrecompile_QueryService memory query_service; - return ContractRuntimePrecompile(uint8(6), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); + return ContractRuntimePrecompile(uint8(4), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); } function ContractRuntimePrecompile_case_read_event(ContractRuntimePrecompile_ReadEvent memory read_event) @@ -699,7 +667,7 @@ library LineraTypes { ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; ContractRuntimePrecompile_QueryService memory query_service; - return ContractRuntimePrecompile(uint8(7), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); + return ContractRuntimePrecompile(uint8(5), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); } function ContractRuntimePrecompile_case_subscribe_to_events(ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events) @@ -713,7 +681,7 @@ library LineraTypes { ContractRuntimePrecompile_ReadEvent memory read_event; ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; ContractRuntimePrecompile_QueryService memory query_service; - return ContractRuntimePrecompile(uint8(8), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); + return ContractRuntimePrecompile(uint8(6), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); } function ContractRuntimePrecompile_case_unsubscribe_from_events(ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events) @@ -727,7 +695,7 @@ library LineraTypes { ContractRuntimePrecompile_ReadEvent memory read_event; ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; ContractRuntimePrecompile_QueryService memory query_service; - return ContractRuntimePrecompile(uint8(9), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); + return ContractRuntimePrecompile(uint8(7), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); } function ContractRuntimePrecompile_case_query_service(ContractRuntimePrecompile_QueryService memory query_service) @@ -741,7 +709,7 @@ library LineraTypes { ContractRuntimePrecompile_ReadEvent memory read_event; ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; - return ContractRuntimePrecompile(uint8(10), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); + return ContractRuntimePrecompile(uint8(8), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); } function ContractRuntimePrecompile_case_validation_round() @@ -756,7 +724,7 @@ library LineraTypes { ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; ContractRuntimePrecompile_QueryService memory query_service; - return ContractRuntimePrecompile(uint8(11), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); + return ContractRuntimePrecompile(uint8(9), send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service); } function bcs_serialize_ContractRuntimePrecompile(ContractRuntimePrecompile memory input) @@ -764,25 +732,25 @@ library LineraTypes { pure returns (bytes memory) { - if (input.choice == 4) { + if (input.choice == 2) { return abi.encodePacked(input.choice, bcs_serialize_ContractRuntimePrecompile_SendMessage(input.send_message)); } - if (input.choice == 5) { + if (input.choice == 3) { return abi.encodePacked(input.choice, bcs_serialize_ContractRuntimePrecompile_TryCallApplication(input.try_call_application)); } - if (input.choice == 6) { + if (input.choice == 4) { return abi.encodePacked(input.choice, bcs_serialize_ContractRuntimePrecompile_Emit(input.emit_)); } - if (input.choice == 7) { + if (input.choice == 5) { return abi.encodePacked(input.choice, bcs_serialize_ContractRuntimePrecompile_ReadEvent(input.read_event)); } - if (input.choice == 8) { + if (input.choice == 6) { return abi.encodePacked(input.choice, bcs_serialize_ContractRuntimePrecompile_SubscribeToEvents(input.subscribe_to_events)); } - if (input.choice == 9) { + if (input.choice == 7) { return abi.encodePacked(input.choice, bcs_serialize_ContractRuntimePrecompile_UnsubscribeFromEvents(input.unsubscribe_from_events)); } - if (input.choice == 10) { + if (input.choice == 8) { return abi.encodePacked(input.choice, bcs_serialize_ContractRuntimePrecompile_QueryService(input.query_service)); } return abi.encodePacked(input.choice); @@ -797,34 +765,34 @@ library LineraTypes { uint8 choice; (new_pos, choice) = bcs_deserialize_offset_uint8(pos, input); ContractRuntimePrecompile_SendMessage memory send_message; - if (choice == 4) { + if (choice == 2) { (new_pos, send_message) = bcs_deserialize_offset_ContractRuntimePrecompile_SendMessage(new_pos, input); } ContractRuntimePrecompile_TryCallApplication memory try_call_application; - if (choice == 5) { + if (choice == 3) { (new_pos, try_call_application) = bcs_deserialize_offset_ContractRuntimePrecompile_TryCallApplication(new_pos, input); } ContractRuntimePrecompile_Emit memory emit_; - if (choice == 6) { + if (choice == 4) { (new_pos, emit_) = bcs_deserialize_offset_ContractRuntimePrecompile_Emit(new_pos, input); } ContractRuntimePrecompile_ReadEvent memory read_event; - if (choice == 7) { + if (choice == 5) { (new_pos, read_event) = bcs_deserialize_offset_ContractRuntimePrecompile_ReadEvent(new_pos, input); } ContractRuntimePrecompile_SubscribeToEvents memory subscribe_to_events; - if (choice == 8) { + if (choice == 6) { (new_pos, subscribe_to_events) = bcs_deserialize_offset_ContractRuntimePrecompile_SubscribeToEvents(new_pos, input); } ContractRuntimePrecompile_UnsubscribeFromEvents memory unsubscribe_from_events; - if (choice == 9) { + if (choice == 7) { (new_pos, unsubscribe_from_events) = bcs_deserialize_offset_ContractRuntimePrecompile_UnsubscribeFromEvents(new_pos, input); } ContractRuntimePrecompile_QueryService memory query_service; - if (choice == 10) { + if (choice == 8) { (new_pos, query_service) = bcs_deserialize_offset_ContractRuntimePrecompile_QueryService(new_pos, input); } - require(choice < 12); + require(choice < 10); return (new_pos, ContractRuntimePrecompile(choice, send_message, try_call_application, emit_, read_event, subscribe_to_events, unsubscribe_from_events, query_service)); } @@ -1223,41 +1191,6 @@ library LineraTypes { return value; } - struct MessageIsBouncing { - OptionBool value; - } - - function bcs_serialize_MessageIsBouncing(MessageIsBouncing memory input) - internal - pure - returns (bytes memory) - { - return bcs_serialize_OptionBool(input.value); - } - - function bcs_deserialize_offset_MessageIsBouncing(uint256 pos, bytes memory input) - internal - pure - returns (uint256, MessageIsBouncing memory) - { - uint256 new_pos; - OptionBool value; - (new_pos, value) = bcs_deserialize_offset_OptionBool(pos, input); - return (new_pos, MessageIsBouncing(value)); - } - - function bcs_deserialize_MessageIsBouncing(bytes memory input) - internal - pure - returns (MessageIsBouncing memory) - { - uint256 new_pos; - MessageIsBouncing memory value; - (new_pos, value) = bcs_deserialize_offset_MessageIsBouncing(0, input); - require(new_pos == input.length, "incomplete deserialization"); - return value; - } - struct OptionAccountOwner { opt_AccountOwner value; } @@ -1328,54 +1261,6 @@ library LineraTypes { return value; } - enum OptionBool { None, True, False } - - function bcs_serialize_OptionBool(OptionBool input) - internal - pure - returns (bytes memory) - { - if (input == OptionBool.None) { - return abi.encodePacked(uint8(0)); - } - if (input == OptionBool.False) { - return abi.encodePacked(uint8(1), uint8(0)); - } - return abi.encodePacked(uint8(1), uint8(1)); - } - - function bcs_deserialize_offset_OptionBool(uint256 pos, bytes memory input) - internal - pure - returns (uint256, OptionBool) - { - uint8 choice = uint8(input[pos]); - if (choice == 0) { - return (pos + 1, OptionBool.None); - } else { - require(choice == 1); - uint8 value = uint8(input[pos + 1]); - if (value == 0) { - return (pos + 2, OptionBool.False); - } else { - require(value == 1); - return (pos + 2, OptionBool.True); - } - } - } - - function bcs_deserialize_OptionBool(bytes memory input) - internal - pure - returns (OptionBool) - { - uint256 new_pos; - OptionBool value; - (new_pos, value) = bcs_deserialize_offset_OptionBool(0, input); - require(new_pos == input.length, "incomplete deserialization"); - return value; - } - struct OptionChainId { opt_ChainId value; } diff --git a/linera-execution/solidity/LineraTypes.yaml b/linera-execution/solidity/LineraTypes.yaml index e91f76bb196e..0bb077ce3eeb 100644 --- a/linera-execution/solidity/LineraTypes.yaml +++ b/linera-execution/solidity/LineraTypes.yaml @@ -80,14 +80,6 @@ BlockHeight: ChainId: NEWTYPESTRUCT: TYPENAME: CryptoHash -BlockHeight: - NEWTYPESTRUCT: U64 -MessageIsBouncing: - NEWTYPESTRUCT: - OPTION: BOOL -MessageIsBouncing: - NEWTYPESTRUCT: - OPTION: BOOL OptionU32: NEWTYPESTRUCT: OPTION: U32 @@ -136,30 +128,26 @@ ContractRuntimePrecompile: 0: AuthenticatedSigner: UNIT 1: - MessageOriginChainId: UNIT - 2: - MessageIsBouncing: UNIT - 3: AuthenticatedCallerId: UNIT - 4: + 2: SendMessage: STRUCT: - destination: TYPENAME: ChainId - message: BYTES - 5: + 3: TryCallApplication: STRUCT: - target: TYPENAME: ApplicationId - argument: BYTES - 6: + 4: Emit: STRUCT: - stream_name: TYPENAME: StreamName - value: BYTES - 7: + 5: ReadEvent: STRUCT: - chain_id: @@ -167,7 +155,7 @@ ContractRuntimePrecompile: - stream_name: TYPENAME: StreamName - index: U32 - 8: + 6: SubscribeToEvents: STRUCT: - chain_id: @@ -176,7 +164,7 @@ ContractRuntimePrecompile: TYPENAME: ApplicationId - stream_name: TYPENAME: StreamName - 9: + 7: UnsubscribeFromEvents: STRUCT: - chain_id: @@ -185,13 +173,13 @@ ContractRuntimePrecompile: TYPENAME: ApplicationId - stream_name: TYPENAME: StreamName - 10: + 8: QueryService: STRUCT: - application_id: TYPENAME: ApplicationId - query: BYTES - 11: + 9: ValidationRound: UNIT ServiceRuntimePrecompile: ENUM: diff --git a/linera-execution/src/evm/revm.rs b/linera-execution/src/evm/revm.rs index 6cacdce6b1a6..3b5faa958a9c 100644 --- a/linera-execution/src/evm/revm.rs +++ b/linera-execution/src/evm/revm.rs @@ -44,7 +44,7 @@ use crate::{ /// This is the selector of the `execute_message` that should be called /// only from a submitted message -const EXECUTE_MESSAGE_SELECTOR: &[u8] = &[173, 125, 234, 205]; +const EXECUTE_MESSAGE_SELECTOR: &[u8] = &[164, 240, 137, 222]; /// This is the selector of the `process_streams` that should be called /// only from a submitted message @@ -108,7 +108,7 @@ mod tests { // selector directly. #[test] fn check_execute_message_selector() { - let selector = &keccak256("execute_message(bytes)".as_bytes())[..4]; + let selector = &keccak256("execute_message(bool,bytes32,bytes)".as_bytes())[..4]; assert_eq!(selector, EXECUTE_MESSAGE_SELECTOR); } @@ -205,14 +205,19 @@ fn get_revm_instantiation_bytes(value: Vec) -> Vec { argument.abi_encode() } -fn get_revm_execute_message_bytes(value: Vec) -> Vec { - use alloy_primitives::Bytes; +fn get_revm_execute_message_bytes(is_bouncing: bool, origin: ChainId, value: Vec) -> Vec { + use alloy_primitives::{Bytes, B256}; use alloy_sol_types::{sol, SolCall}; sol! { - function execute_message(bytes value); + function execute_message(bool is_bouncing, bytes32 source_chain_id, bytes value); } let value = Bytes::from(value); - let argument = execute_messageCall { value }; + let source_chain_id = B256::from(<[u8; 32]>::from(origin.0)); + let argument = execute_messageCall { + is_bouncing, + source_chain_id, + value, + }; argument.abi_encode() } @@ -505,10 +510,6 @@ enum BaseRuntimePrecompile { enum ContractRuntimePrecompile { /// Calling `authenticated_signer` of `ContractRuntime` AuthenticatedSigner, - /// Calling `message_origin_chain_id` of `ContractRuntime` - MessageOriginChainId, - /// Calling `message_is_bouncing` of `ContractRuntime` - MessageIsBouncing, /// Calling `authenticated_caller_id` of `ContractRuntime` AuthenticatedCallerId, /// Calling `send_message` of `ContractRuntime` @@ -723,15 +724,6 @@ impl<'a> ContractPrecompile { Ok(bcs::to_bytes(&account_owner)?) } - ContractRuntimePrecompile::MessageOriginChainId => { - let origin_chain_id = runtime.message_origin_chain_id()?; - Ok(bcs::to_bytes(&origin_chain_id)?) - } - - ContractRuntimePrecompile::MessageIsBouncing => { - let result = runtime.message_is_bouncing()?; - Ok(bcs::to_bytes(&result)?) - } ContractRuntimePrecompile::AuthenticatedCallerId => { let application_id = runtime.authenticated_caller_id()?; Ok(bcs::to_bytes(&application_id)?) @@ -1188,14 +1180,19 @@ where Ok(output) } - fn execute_message(&mut self, message: Vec) -> Result<(), ExecutionError> { + fn execute_message( + &mut self, + is_bouncing: bool, + origin: ChainId, + message: Vec, + ) -> Result<(), ExecutionError> { self.db.set_contract_address()?; ensure_selector_presence( &self.module, EXECUTE_MESSAGE_SELECTOR, - "function execute_message(bytes)", + "function execute_message(bool,bytes32,bytes)", )?; - let operation = get_revm_execute_message_bytes(message); + let operation = get_revm_execute_message_bytes(is_bouncing, origin, message); let caller = self.get_msg_address()?; self.execute_no_return_operation(operation, "message", caller) } diff --git a/linera-execution/src/lib.rs b/linera-execution/src/lib.rs index 4c35332f2032..859fb165c3a4 100644 --- a/linera-execution/src/lib.rs +++ b/linera-execution/src/lib.rs @@ -333,7 +333,12 @@ pub trait UserContract { fn execute_operation(&mut self, operation: Vec) -> Result, ExecutionError>; /// Applies a message originating from a cross-chain message. - fn execute_message(&mut self, message: Vec) -> Result<(), ExecutionError>; + fn execute_message( + &mut self, + is_bouncing: bool, + origin: ChainId, + message: Vec, + ) -> Result<(), ExecutionError>; /// Reacts to new events on streams this application subscribes to. fn process_streams(&mut self, updates: Vec) -> Result<(), ExecutionError>; @@ -693,13 +698,6 @@ pub trait ContractRuntime: BaseRuntime { /// The authenticated signer for this execution, if there is one. fn authenticated_signer(&mut self) -> Result, ExecutionError>; - /// If the current message (if there is one) was rejected by its destination and is now - /// bouncing back. - fn message_is_bouncing(&mut self) -> Result, ExecutionError>; - - /// The chain ID where the current message originated from, if there is one. - fn message_origin_chain_id(&mut self) -> Result, ExecutionError>; - /// The optional authenticated caller application ID, if it was provided and if there is one /// based on the execution context. fn authenticated_caller_id(&mut self) -> Result, ExecutionError>; diff --git a/linera-execution/src/runtime.rs b/linera-execution/src/runtime.rs index 0c3b606b8bde..ea82899af385 100644 --- a/linera-execution/src/runtime.rs +++ b/linera-execution/src/runtime.rs @@ -1096,7 +1096,9 @@ impl ContractSyncRuntimeHandle { UserAction::Operation(_context, operation) => { code.execute_operation(operation).map(Option::Some) } - UserAction::Message(_context, message) => code.execute_message(message).map(|()| None), + UserAction::Message(context, message) => code + .execute_message(context.is_bouncing, context.origin, message) + .map(|()| None), UserAction::ProcessStreams(_context, updates) => { code.process_streams(updates).map(|()| None) } @@ -1172,20 +1174,6 @@ impl ContractRuntime for ContractSyncRuntimeHandle { Ok(self.inner().authenticated_signer) } - fn message_is_bouncing(&mut self) -> Result, ExecutionError> { - Ok(self - .inner() - .executing_message - .map(|metadata| metadata.is_bouncing)) - } - - fn message_origin_chain_id(&mut self) -> Result, ExecutionError> { - Ok(self - .inner() - .executing_message - .map(|metadata| metadata.origin)) - } - fn authenticated_caller_id(&mut self) -> Result, ExecutionError> { let this = self.inner(); if this.call_stack.len() <= 1 { diff --git a/linera-execution/src/test_utils/mock_application.rs b/linera-execution/src/test_utils/mock_application.rs index 546601cbed3a..4e91abb3e024 100644 --- a/linera-execution/src/test_utils/mock_application.rs +++ b/linera-execution/src/test_utils/mock_application.rs @@ -131,7 +131,9 @@ type ExecuteOperationHandler = Box< + Sync, >; type ExecuteMessageHandler = Box< - dyn FnOnce(&mut ContractSyncRuntimeHandle, Vec) -> Result<(), ExecutionError> + Send + Sync, + dyn FnOnce(&mut ContractSyncRuntimeHandle, bool, ChainId, Vec) -> Result<(), ExecutionError> + + Send + + Sync, >; type ProcessStreamHandler = Box< dyn FnOnce(&mut ContractSyncRuntimeHandle, Vec) -> Result<(), ExecutionError> @@ -206,7 +208,12 @@ impl ExpectedCall { /// [`UserContract::execute_message`] implementation, which is handled by the provided /// `handler`. pub fn execute_message( - handler: impl FnOnce(&mut ContractSyncRuntimeHandle, Vec) -> Result<(), ExecutionError> + handler: impl FnOnce( + &mut ContractSyncRuntimeHandle, + bool, + ChainId, + Vec, + ) -> Result<(), ExecutionError> + Send + Sync + 'static, @@ -304,9 +311,16 @@ impl UserContract for MockApplicationInstance { } } - fn execute_message(&mut self, message: Vec) -> Result<(), ExecutionError> { + fn execute_message( + &mut self, + is_bouncing: bool, + origin: ChainId, + message: Vec, + ) -> Result<(), ExecutionError> { match self.next_expected_call() { - Some(ExpectedCall::ExecuteMessage(handler)) => handler(&mut self.runtime, message), + Some(ExpectedCall::ExecuteMessage(handler)) => { + handler(&mut self.runtime, is_bouncing, origin, message) + } Some(unexpected_call) => panic!( "Expected a call to `execute_message`, got a call to `{unexpected_call}` instead." ), diff --git a/linera-execution/src/wasm/entrypoints.rs b/linera-execution/src/wasm/entrypoints.rs index ddeee552a114..23b3809aa149 100644 --- a/linera-execution/src/wasm/entrypoints.rs +++ b/linera-execution/src/wasm/entrypoints.rs @@ -3,7 +3,7 @@ //! Wasm entrypoints for contracts and services. -use linera_base::data_types::StreamUpdate; +use linera_base::{data_types::StreamUpdate, identifiers::ChainId}; use linera_witty::wit_import; /// WIT entrypoints for application contracts. @@ -11,7 +11,7 @@ use linera_witty::wit_import; pub trait ContractEntrypoints { fn instantiate(argument: Vec); fn execute_operation(operation: Vec) -> Vec; - fn execute_message(message: Vec); + fn execute_message(is_bouncing: bool, origin: ChainId, message: Vec); fn process_streams(streams: Vec); fn finalize(); } diff --git a/linera-execution/src/wasm/runtime_api.rs b/linera-execution/src/wasm/runtime_api.rs index a31b3a055040..93053957e3fb 100644 --- a/linera-execution/src/wasm/runtime_api.rs +++ b/linera-execution/src/wasm/runtime_api.rs @@ -400,27 +400,6 @@ where .map_err(|error| RuntimeError::Custom(error.into())) } - /// Returns `Some(true)` if the incoming message was rejected from the original destination and - /// is now bouncing back, `Some(false)` if the message is being currently being delivered to - /// its original destination, or [`None`] if not executing an incoming message. - fn message_is_bouncing(caller: &mut Caller) -> Result, RuntimeError> { - caller - .user_data_mut() - .runtime - .message_is_bouncing() - .map_err(|error| RuntimeError::Custom(error.into())) - } - - /// Returns the chain ID where the current message originated from, or [`None`] if not executing - /// an incoming message. - fn message_origin_chain_id(caller: &mut Caller) -> Result, RuntimeError> { - caller - .user_data_mut() - .runtime - .message_origin_chain_id() - .map_err(|error| RuntimeError::Custom(error.into())) - } - /// Returns the authenticated caller ID, if the caller configured it and if the current context. fn authenticated_caller_id(caller: &mut Caller) -> Result, RuntimeError> { caller diff --git a/linera-execution/src/wasm/wasmer.rs b/linera-execution/src/wasm/wasmer.rs index c07ff3ab1fd5..1c9930479db7 100644 --- a/linera-execution/src/wasm/wasmer.rs +++ b/linera-execution/src/wasm/wasmer.rs @@ -5,7 +5,10 @@ use std::{marker::Unpin, sync::LazyLock}; -use linera_base::data_types::{Bytecode, StreamUpdate}; +use linera_base::{ + data_types::{Bytecode, StreamUpdate}, + identifiers::ChainId, +}; use linera_witty::{ wasmer::{EntrypointInstance, InstanceBuilder}, ExportTo, @@ -140,9 +143,14 @@ where .map_err(WasmExecutionError::from)?) } - fn execute_message(&mut self, message: Vec) -> Result<(), ExecutionError> { + fn execute_message( + &mut self, + is_bouncing: bool, + origin: ChainId, + message: Vec, + ) -> Result<(), ExecutionError> { ContractEntrypoints::new(&mut self.instance) - .execute_message(message) + .execute_message(is_bouncing, origin, message) .map_err(WasmExecutionError::from)?; Ok(()) } diff --git a/linera-execution/src/wasm/wasmtime.rs b/linera-execution/src/wasm/wasmtime.rs index 15cedd950dc9..abb74417ed41 100644 --- a/linera-execution/src/wasm/wasmtime.rs +++ b/linera-execution/src/wasm/wasmtime.rs @@ -5,7 +5,10 @@ use std::sync::LazyLock; -use linera_base::data_types::{Bytecode, StreamUpdate}; +use linera_base::{ + data_types::{Bytecode, StreamUpdate}, + identifiers::ChainId, +}; use linera_witty::{wasmtime::EntrypointInstance, ExportTo}; use tokio::sync::Mutex; use wasmtime::{Config, Engine, Linker, Module, Store}; @@ -145,9 +148,14 @@ where Ok(result) } - fn execute_message(&mut self, message: Vec) -> Result<(), ExecutionError> { + fn execute_message( + &mut self, + is_bouncing: bool, + origin: ChainId, + message: Vec, + ) -> Result<(), ExecutionError> { ContractEntrypoints::new(&mut self.instance) - .execute_message(message) + .execute_message(is_bouncing, origin, message) .map_err(WasmExecutionError::from)?; Ok(()) } diff --git a/linera-execution/tests/fee_consumption.rs b/linera-execution/tests/fee_consumption.rs index 19053849ce3c..42e7379ae979 100644 --- a/linera-execution/tests/fee_consumption.rs +++ b/linera-execution/tests/fee_consumption.rs @@ -265,12 +265,14 @@ async fn test_fee_consumption( oracle_responses.extend(spend.expected_oracle_responses()); } - application.expect_call(ExpectedCall::execute_message(move |runtime, _operation| { - for spend in spends { - spend.execute(runtime)?; - } - Ok(()) - })); + application.expect_call(ExpectedCall::execute_message( + move |runtime, _is_bouncing, _origin, _message| { + for spend in spends { + spend.execute(runtime)?; + } + Ok(()) + }, + )); application.expect_call(ExpectedCall::default_finalize()); let refund_grant_to = authenticated_signer diff --git a/linera-execution/tests/test_execution.rs b/linera-execution/tests/test_execution.rs index 088abd8b1132..54271962d39d 100644 --- a/linera-execution/tests/test_execution.rs +++ b/linera-execution/tests/test_execution.rs @@ -1406,10 +1406,12 @@ async fn test_message_receipt_spending_chain_balance( owner: AccountOwner::CHAIN, }; - application.expect_call(ExpectedCall::execute_message(move |runtime, _operation| { - runtime.transfer(receiver_chain_account, recipient, amount)?; - Ok(()) - })); + application.expect_call(ExpectedCall::execute_message( + move |runtime, _is_bouncing, _origin, _message| { + runtime.transfer(receiver_chain_account, recipient, amount)?; + Ok(()) + }, + )); application.expect_call(ExpectedCall::default_finalize()); let context = create_dummy_message_context(chain_id, authenticated_signer); diff --git a/linera-sdk/src/contract/mod.rs b/linera-sdk/src/contract/mod.rs index 0723eaf755ff..df87378f6971 100644 --- a/linera-sdk/src/contract/mod.rs +++ b/linera-sdk/src/contract/mod.rs @@ -71,7 +71,7 @@ macro_rules! contract { ) } - fn execute_message(message: Vec) { + fn execute_message(is_bouncing: bool, origin: $crate::contract::wit::exports::linera::app::contract_entrypoints::ChainId, message: Vec) { use $crate::util::BlockingWait; $crate::contract::run_async_entrypoint::<$contract, _, _>( unsafe { &mut CONTRACT }, @@ -80,7 +80,10 @@ macro_rules! contract { $crate::bcs::from_bytes(&message) .expect("Failed to deserialize message"); - contract.execute_message(message).blocking_wait() + // Convert WIT ChainId to SDK ChainId + let origin: $crate::ChainId = origin.into(); + + contract.execute_message(is_bouncing, origin, message).blocking_wait() }, ) } diff --git a/linera-sdk/src/contract/runtime.rs b/linera-sdk/src/contract/runtime.rs index 51a6c93acae5..8f36e3622b38 100644 --- a/linera-sdk/src/contract/runtime.rs +++ b/linera-sdk/src/contract/runtime.rs @@ -35,8 +35,6 @@ where chain_id: Option, authenticated_signer: Option>, block_height: Option, - message_is_bouncing: Option>, - message_origin_chain_id: Option>, authenticated_caller_id: Option>, timestamp: Option, } @@ -54,8 +52,6 @@ where chain_id: None, authenticated_signer: None, block_height: None, - message_is_bouncing: None, - message_origin_chain_id: None, authenticated_caller_id: None, timestamp: None, } @@ -179,22 +175,6 @@ where .get_or_insert_with(|| contract_wit::authenticated_signer().map(AccountOwner::from)) } - /// Returns [`true`] if the incoming message was rejected from the original destination and is - /// now bouncing back, or [`None`] if not executing an incoming message. - pub fn message_is_bouncing(&mut self) -> Option { - *self - .message_is_bouncing - .get_or_insert_with(contract_wit::message_is_bouncing) - } - - /// Returns the chain ID where the incoming message originated from, or [`None`] if not executing - /// an incoming message. - pub fn message_origin_chain_id(&mut self) -> Option { - *self - .message_origin_chain_id - .get_or_insert_with(|| contract_wit::message_origin_chain_id().map(ChainId::from)) - } - /// Returns the authenticated caller ID, if the caller configured it and if the current context /// is executing a cross-application call. pub fn authenticated_caller_id(&mut self) -> Option { diff --git a/linera-sdk/src/contract/test_runtime.rs b/linera-sdk/src/contract/test_runtime.rs index fcf080c99540..93aa8e832ffe 100644 --- a/linera-sdk/src/contract/test_runtime.rs +++ b/linera-sdk/src/contract/test_runtime.rs @@ -57,8 +57,6 @@ where authenticated_signer: Option>, block_height: Option, round: Option, - message_is_bouncing: Option>, - message_origin_chain_id: Option>, authenticated_caller_id: Option>, timestamp: Option, chain_balance: Option, @@ -106,8 +104,6 @@ where authenticated_signer: None, block_height: None, round: None, - message_is_bouncing: None, - message_origin_chain_id: None, authenticated_caller_id: None, timestamp: None, chain_balance: None, @@ -290,51 +286,6 @@ where ) } - /// Configures the `message_is_bouncing` flag to return during the test. - pub fn with_message_is_bouncing( - mut self, - message_is_bouncing: impl Into>, - ) -> Self { - self.message_is_bouncing = Some(message_is_bouncing.into()); - self - } - - /// Configures the `message_is_bouncing` flag to return during the test. - pub fn set_message_is_bouncing( - &mut self, - message_is_bouncing: impl Into>, - ) -> &mut Self { - self.message_is_bouncing = Some(message_is_bouncing.into()); - self - } - - /// Returns [`true`] if the incoming message was rejected from the original destination and is - /// now bouncing back, or [`None`] if not executing an incoming message. - pub fn message_is_bouncing(&mut self) -> Option { - self.message_is_bouncing.expect( - "`message_is_bouncing` flag has not been mocked, \ - please call `MockContractRuntime::set_message_is_bouncing` first", - ) - } - - /// Configures the `message_origin_chain_id` to return during the test. - pub fn set_message_origin_chain_id( - &mut self, - message_origin_chain_id: impl Into>, - ) -> &mut Self { - self.message_origin_chain_id = Some(message_origin_chain_id.into()); - self - } - - /// Returns the chain ID where the incoming message originated from, or [`None`] if not - /// executing an incoming message. - pub fn message_origin_chain_id(&mut self) -> Option { - self.message_origin_chain_id.expect( - "`message_origin_chain_id` has not been mocked, \ - please call `MockContractRuntime::set_message_origin_chain_id` first", - ) - } - /// Configures the authenticated caller ID to return during the test. pub fn with_authenticated_caller_id( mut self, diff --git a/linera-sdk/src/lib.rs b/linera-sdk/src/lib.rs index 5b59390fe9ca..8bccd55eee35 100644 --- a/linera-sdk/src/lib.rs +++ b/linera-sdk/src/lib.rs @@ -50,6 +50,7 @@ pub use linera_base::{ abi, data_types::{Resources, SendMessageRequest}, ensure, http, + identifiers::ChainId, }; use linera_base::{ abi::{ContractAbi, ServiceAbi, WithContractAbi, WithServiceAbi}, @@ -131,7 +132,7 @@ pub trait Contract: WithContractAbi + ContractAbi + Sized { /// /// For a message to be executed, a user must mark it to be received in a block of the receiver /// chain. - async fn execute_message(&mut self, message: Self::Message); + async fn execute_message(&mut self, is_bouncing: bool, origin: ChainId, message: Self::Message); /// Reacts to new events on streams. /// diff --git a/linera-sdk/wit/contract-entrypoints.wit b/linera-sdk/wit/contract-entrypoints.wit index 672a59f1374a..18f11a5779ec 100644 --- a/linera-sdk/wit/contract-entrypoints.wit +++ b/linera-sdk/wit/contract-entrypoints.wit @@ -3,7 +3,7 @@ package linera:app; interface contract-entrypoints { instantiate: func(argument: list); execute-operation: func(operation: list) -> list; - execute-message: func(message: list); + execute-message: func(is-bouncing: bool, origin: chain-id, message: list); process-streams: func(streams: list); finalize: func(); diff --git a/linera-sdk/wit/contract-runtime-api.wit b/linera-sdk/wit/contract-runtime-api.wit index 2fbfd1703fc1..100df7bc45de 100644 --- a/linera-sdk/wit/contract-runtime-api.wit +++ b/linera-sdk/wit/contract-runtime-api.wit @@ -2,8 +2,6 @@ package linera:app; interface contract-runtime-api { authenticated-signer: func() -> option; - message-is-bouncing: func() -> option; - message-origin-chain-id: func() -> option; authenticated-caller-id: func() -> option; send-message: func(message: send-message-request); transfer: func(source: account-owner, destination: account, amount: amount); diff --git a/linera-service/template/contract.rs.template b/linera-service/template/contract.rs.template index 1204c2981ef3..f941fdbabd85 100644 --- a/linera-service/template/contract.rs.template +++ b/linera-service/template/contract.rs.template @@ -5,7 +5,7 @@ mod state; use linera_sdk::{{ linera_base_types::WithContractAbi, views::{{RootView, View}}, - Contract, ContractRuntime, + ChainId, Contract, ContractRuntime, }}; use {module_name}::Operation; @@ -50,7 +50,13 @@ impl Contract for {project_name}Contract {{ }} }} - async fn execute_message(&mut self, _message: Self::Message) {{}} + async fn execute_message( + &mut self, + _is_bouncing: bool, + _origin: ChainId, + _message: Self::Message, + ) {{ + }} async fn store(mut self) {{ self.state.save().await.expect("Failed to save state"); diff --git a/linera-service/tests/fixtures/erc20_shared.sol b/linera-service/tests/fixtures/erc20_shared.sol index 8bbdc739aa11..c6b308288e76 100644 --- a/linera-service/tests/fixtures/erc20_shared.sol +++ b/linera-service/tests/fixtures/erc20_shared.sol @@ -70,11 +70,9 @@ contract ERC20_shared is Context, IERC20, IERC20Errors { * This is the function run on the receiving chain in order to credit * the user with the tokens. */ - function execute_message(bytes memory input) external { + function execute_message(bool is_bouncing, bytes32 source_chain_id, bytes memory input) external { (address source, address destination, uint256 amount) = abi.decode(input, (address, address, uint256)); - Linera.OptionBool result = Linera.message_is_bouncing(); - require(result != Linera.OptionBool.None); - if (result == Linera.OptionBool.True) { + if (is_bouncing) { _mint(source, amount); } else { _mint(destination, amount); diff --git a/linera-service/tests/fixtures/evm_example_execute_message.sol b/linera-service/tests/fixtures/evm_example_execute_message.sol index 25ac85c537f7..fe77faec76a6 100644 --- a/linera-service/tests/fixtures/evm_example_execute_message.sol +++ b/linera-service/tests/fixtures/evm_example_execute_message.sol @@ -6,7 +6,7 @@ import "./Linera.sol"; contract ExampleExecuteMessage { uint64 value; - Linera.opt_ChainId last_message_origin_chain_id; + bytes32 last_message_origin_chain_id; constructor(uint64 test_value) { require(test_value == 42); @@ -17,10 +17,10 @@ contract ExampleExecuteMessage { value = read_value; } - function execute_message(bytes memory input) external { + function execute_message(bool is_bouncing, bytes32 origin, bytes memory input) external { uint64 increment = abi.decode(input, (uint64)); value = value + increment; - last_message_origin_chain_id = Linera.message_origin_chain_id(); + last_message_origin_chain_id = origin; } function move_value_to_chain(bytes32 chain_id, uint64 moved_value) external {