diff --git a/examples/amm/src/contract.rs b/examples/amm/src/contract.rs index d5881531c11..f8e0e4ca0a9 100644 --- a/examples/amm/src/contract.rs +++ b/examples/amm/src/contract.rs @@ -5,7 +5,7 @@ mod state; -use amm::{AmmAbi, AmmError, Message, Operation}; +use amm::{AmmAbi, AmmError, Message, Operation, Parameters}; use async_trait::async_trait; use fungible::{Account, FungibleTokenAbi}; use linera_sdk::{ @@ -34,6 +34,8 @@ impl Contract for AmmContract { type Storage = ViewStateStorage; type State = Amm; type Message = Message; + type InitializationArgument = (); + type Parameters = Parameters; async fn new(state: Amm, runtime: ContractRuntime) -> Result { Ok(AmmContract { state, runtime }) diff --git a/examples/amm/src/lib.rs b/examples/amm/src/lib.rs index fc98d16c00b..f345c52704b 100644 --- a/examples/amm/src/lib.rs +++ b/examples/amm/src/lib.rs @@ -184,8 +184,6 @@ use thiserror::Error; pub struct AmmAbi; impl ContractAbi for AmmAbi { - type InitializationArgument = (); - type Parameters = Parameters; type Operation = Operation; type Response = (); } @@ -193,7 +191,6 @@ impl ContractAbi for AmmAbi { impl ServiceAbi for AmmAbi { type Query = Request; type QueryResponse = Response; - type Parameters = Parameters; } /// Operations that can be sent to the application. diff --git a/examples/amm/src/service.rs b/examples/amm/src/service.rs index 60b982c62c6..a09e4a64a30 100644 --- a/examples/amm/src/service.rs +++ b/examples/amm/src/service.rs @@ -7,7 +7,7 @@ mod state; use std::sync::Arc; -use amm::{AmmError, Operation}; +use amm::{AmmError, Operation, Parameters}; use async_graphql::{EmptySubscription, Object, Request, Response, Schema}; use linera_sdk::{base::WithServiceAbi, Service, ServiceRuntime, ViewStateStorage}; @@ -27,6 +27,7 @@ impl Service for AmmService { type Error = AmmError; type Storage = ViewStateStorage; type State = Amm; + type Parameters = Parameters; async fn new(state: Self::State, _runtime: ServiceRuntime) -> Result { Ok(AmmService { diff --git a/examples/counter/src/contract.rs b/examples/counter/src/contract.rs index f5fa5c5bbfb..cc51e234faf 100644 --- a/examples/counter/src/contract.rs +++ b/examples/counter/src/contract.rs @@ -29,6 +29,8 @@ impl Contract for CounterContract { type Storage = SimpleStateStorage; type State = Counter; type Message = (); + type InitializationArgument = u64; + type Parameters = (); async fn new(state: Counter, runtime: ContractRuntime) -> Result { Ok(CounterContract { state, runtime }) diff --git a/examples/counter/src/lib.rs b/examples/counter/src/lib.rs index 4c7e737f8d3..92cc54c8a92 100644 --- a/examples/counter/src/lib.rs +++ b/examples/counter/src/lib.rs @@ -116,8 +116,6 @@ use linera_sdk::base::{ContractAbi, ServiceAbi}; pub struct CounterAbi; impl ContractAbi for CounterAbi { - type InitializationArgument = u64; - type Parameters = (); type Operation = u64; type Response = u64; } @@ -125,5 +123,4 @@ impl ContractAbi for CounterAbi { impl ServiceAbi for CounterAbi { type Query = Request; type QueryResponse = Response; - type Parameters = (); } diff --git a/examples/counter/src/service.rs b/examples/counter/src/service.rs index 1393e2f345e..1ab04e438a9 100644 --- a/examples/counter/src/service.rs +++ b/examples/counter/src/service.rs @@ -25,6 +25,7 @@ impl Service for CounterService { type Error = Error; type Storage = SimpleStateStorage; type State = Counter; + type Parameters = (); async fn new(state: Self::State, _runtime: ServiceRuntime) -> Result { Ok(CounterService { state }) diff --git a/examples/counter/tests/single_chain.rs b/examples/counter/tests/single_chain.rs index 6982077f27e..47a553e6dcb 100644 --- a/examples/counter/tests/single_chain.rs +++ b/examples/counter/tests/single_chain.rs @@ -13,12 +13,13 @@ use linera_sdk::test::TestValidator; /// which is then checked. #[tokio::test(flavor = "multi_thread")] async fn single_chain_test() { - let (validator, bytecode_id) = TestValidator::with_current_bytecode().await; + let (validator, bytecode_id) = + TestValidator::with_current_bytecode::().await; let mut chain = validator.new_chain().await; let initial_state = 42u64; let application_id = chain - .create_application::(bytecode_id, (), initial_state, vec![]) + .create_application(bytecode_id, (), initial_state, vec![]) .await; let increment = 15u64; diff --git a/examples/crowd-funding/src/contract.rs b/examples/crowd-funding/src/contract.rs index fd98a17c7a8..a10fa1b322d 100644 --- a/examples/crowd-funding/src/contract.rs +++ b/examples/crowd-funding/src/contract.rs @@ -34,6 +34,8 @@ impl Contract for CrowdFundingContract { type Storage = ViewStateStorage; type State = CrowdFunding; type Message = Message; + type InitializationArgument = InitializationArgument; + type Parameters = ApplicationId; async fn new(state: CrowdFunding, runtime: ContractRuntime) -> Result { Ok(CrowdFundingContract { state, runtime }) diff --git a/examples/crowd-funding/src/lib.rs b/examples/crowd-funding/src/lib.rs index 6f9db14a9a0..5d5874798cb 100644 --- a/examples/crowd-funding/src/lib.rs +++ b/examples/crowd-funding/src/lib.rs @@ -281,7 +281,7 @@ query { use async_graphql::{Request, Response, SimpleObject}; use linera_sdk::{ - base::{AccountOwner, Amount, ApplicationId, ContractAbi, ServiceAbi, Timestamp}, + base::{AccountOwner, Amount, ContractAbi, ServiceAbi, Timestamp}, graphql::GraphQLMutationRoot, }; use serde::{Deserialize, Serialize}; @@ -289,14 +289,11 @@ use serde::{Deserialize, Serialize}; pub struct CrowdFundingAbi; impl ContractAbi for CrowdFundingAbi { - type InitializationArgument = InitializationArgument; - type Parameters = ApplicationId; type Operation = Operation; type Response = (); } impl ServiceAbi for CrowdFundingAbi { - type Parameters = ApplicationId; type Query = Request; type QueryResponse = Response; } diff --git a/examples/crowd-funding/src/service.rs b/examples/crowd-funding/src/service.rs index 26f5d0d912d..c83bb2b046e 100644 --- a/examples/crowd-funding/src/service.rs +++ b/examples/crowd-funding/src/service.rs @@ -10,7 +10,9 @@ use std::sync::Arc; use async_graphql::{EmptySubscription, Request, Response, Schema}; use crowd_funding::Operation; use linera_sdk::{ - base::WithServiceAbi, graphql::GraphQLMutationRoot, Service, ServiceRuntime, ViewStateStorage, + base::{ApplicationId, WithServiceAbi}, + graphql::GraphQLMutationRoot, + Service, ServiceRuntime, ViewStateStorage, }; use state::CrowdFunding; use thiserror::Error; @@ -29,6 +31,7 @@ impl Service for CrowdFundingService { type Error = Error; type Storage = ViewStateStorage; type State = CrowdFunding; + type Parameters = ApplicationId; async fn new(state: Self::State, _runtime: ServiceRuntime) -> Result { Ok(CrowdFundingService { diff --git a/examples/crowd-funding/tests/campaign_lifecycle.rs b/examples/crowd-funding/tests/campaign_lifecycle.rs index 556459688f3..1441cd22fcb 100644 --- a/examples/crowd-funding/tests/campaign_lifecycle.rs +++ b/examples/crowd-funding/tests/campaign_lifecycle.rs @@ -8,8 +8,9 @@ use std::iter; use crowd_funding::{CrowdFundingAbi, InitializationArgument, Operation}; +use fungible::FungibleTokenAbi; use linera_sdk::{ - base::{AccountOwner, Amount, Timestamp}, + base::{AccountOwner, Amount, ApplicationId, Timestamp}, test::TestValidator, }; @@ -24,7 +25,12 @@ async fn collect_pledges() { let target_amount = Amount::from_tokens(220); let pledge_amount = Amount::from_tokens(75); - let (validator, bytecode_id) = TestValidator::with_current_bytecode().await; + let (validator, bytecode_id) = TestValidator::with_current_bytecode::< + CrowdFundingAbi, + ApplicationId, + InitializationArgument, + >() + .await; let fungible_publisher_chain = validator.new_chain().await; let mut campaign_chain = validator.new_chain().await; @@ -47,7 +53,7 @@ async fn collect_pledges() { target: target_amount, }; let campaign_id = campaign_chain - .create_application::( + .create_application( bytecode_id, token_id, campaign_state, @@ -121,7 +127,12 @@ async fn cancel_successful_campaign() { let target_amount = Amount::from_tokens(220); let pledge_amount = Amount::from_tokens(75); - let (validator, bytecode_id) = TestValidator::with_current_bytecode().await; + let (validator, bytecode_id) = TestValidator::with_current_bytecode::< + CrowdFundingAbi, + ApplicationId, + InitializationArgument, + >() + .await; let fungible_publisher_chain = validator.new_chain().await; let mut campaign_chain = validator.new_chain().await; @@ -144,7 +155,7 @@ async fn cancel_successful_campaign() { target: target_amount, }; let campaign_id = campaign_chain - .create_application::( + .create_application( bytecode_id, token_id, campaign_state, diff --git a/examples/fungible/src/contract.rs b/examples/fungible/src/contract.rs index ad2df8e24a2..a4a7cbf87b8 100644 --- a/examples/fungible/src/contract.rs +++ b/examples/fungible/src/contract.rs @@ -8,7 +8,9 @@ mod state; use std::str::FromStr; use async_trait::async_trait; -use fungible::{Account, FungibleResponse, FungibleTokenAbi, Message, Operation}; +use fungible::{ + Account, FungibleResponse, FungibleTokenAbi, InitialState, Message, Operation, Parameters, +}; use linera_sdk::{ base::{AccountOwner, Amount, WithContractAbi}, ensure, Contract, ContractRuntime, ViewStateStorage, @@ -34,6 +36,8 @@ impl Contract for FungibleTokenContract { type Storage = ViewStateStorage; type State = FungibleToken; type Message = Message; + type Parameters = Parameters; + type InitializationArgument = InitialState; async fn new( state: FungibleToken, diff --git a/examples/fungible/src/lib.rs b/examples/fungible/src/lib.rs index ce8a0af024b..1a85f44c913 100644 --- a/examples/fungible/src/lib.rs +++ b/examples/fungible/src/lib.rs @@ -266,7 +266,7 @@ pub enum Message { #[cfg(all(any(test, feature = "test"), not(target_arch = "wasm32")))] pub async fn create_with_accounts( validator: &TestValidator, - bytecode_id: BytecodeId, + bytecode_id: BytecodeId, initial_amounts: impl IntoIterator, ) -> ( ApplicationId, diff --git a/examples/fungible/src/service.rs b/examples/fungible/src/service.rs index 1e910393a12..0ad241d1206 100644 --- a/examples/fungible/src/service.rs +++ b/examples/fungible/src/service.rs @@ -8,7 +8,7 @@ mod state; use std::sync::{Arc, Mutex}; use async_graphql::{EmptySubscription, Object, Request, Response, Schema}; -use fungible::Operation; +use fungible::{Operation, Parameters}; use linera_sdk::{ base::{AccountOwner, Amount, WithServiceAbi}, graphql::GraphQLMutationRoot, @@ -35,6 +35,7 @@ impl Service for FungibleTokenService { type Error = Error; type Storage = ViewStateStorage; type State = FungibleToken; + type Parameters = Parameters; async fn new(state: Self::State, runtime: ServiceRuntime) -> Result { Ok(FungibleTokenService { diff --git a/examples/fungible/tests/cross_chain.rs b/examples/fungible/tests/cross_chain.rs index ec8ce26cb39..8c1b7680a18 100644 --- a/examples/fungible/tests/cross_chain.rs +++ b/examples/fungible/tests/cross_chain.rs @@ -5,7 +5,9 @@ #![cfg(not(target_arch = "wasm32"))] -use fungible::{Account, InitialStateBuilder, Operation, Parameters}; +use fungible::{ + Account, FungibleTokenAbi, InitialState, InitialStateBuilder, Operation, Parameters, +}; use linera_sdk::{ base::{AccountOwner, Amount}, test::TestValidator, @@ -21,19 +23,19 @@ async fn test_cross_chain_transfer() { let initial_amount = Amount::from_tokens(20); let transfer_amount = Amount::from_tokens(15); - let (validator, bytecode_id) = TestValidator::with_current_bytecode().await; + let (validator, bytecode_id) = TestValidator::with_current_bytecode::< + fungible::FungibleTokenAbi, + Parameters, + InitialState, + >() + .await; let mut sender_chain = validator.new_chain().await; let sender_account = AccountOwner::from(sender_chain.public_key()); let initial_state = InitialStateBuilder::default().with_account(sender_account, initial_amount); let params = Parameters::new("FUN"); let application_id = sender_chain - .create_application::( - bytecode_id, - params, - initial_state.build(), - vec![], - ) + .create_application(bytecode_id, params, initial_state.build(), vec![]) .await; let receiver_chain = validator.new_chain().await; @@ -79,19 +81,15 @@ async fn test_bouncing_tokens() { let initial_amount = Amount::from_tokens(19); let transfer_amount = Amount::from_tokens(7); - let (validator, bytecode_id) = TestValidator::with_current_bytecode().await; + let (validator, bytecode_id) = + TestValidator::with_current_bytecode::().await; let mut sender_chain = validator.new_chain().await; let sender_account = AccountOwner::from(sender_chain.public_key()); let initial_state = InitialStateBuilder::default().with_account(sender_account, initial_amount); let params = Parameters::new("RET"); let application_id = sender_chain - .create_application::( - bytecode_id, - params, - initial_state.build(), - vec![], - ) + .create_application(bytecode_id, params, initial_state.build(), vec![]) .await; let receiver_chain = validator.new_chain().await; diff --git a/examples/matching-engine/src/contract.rs b/examples/matching-engine/src/contract.rs index ddd5425845c..ef566ea5ecd 100644 --- a/examples/matching-engine/src/contract.rs +++ b/examples/matching-engine/src/contract.rs @@ -13,7 +13,8 @@ use linera_sdk::{ ensure, Contract, ContractRuntime, ViewStateStorage, }; use matching_engine::{ - product_price_amount, MatchingEngineAbi, Message, Operation, Order, OrderId, OrderNature, Price, + product_price_amount, MatchingEngineAbi, Message, Operation, Order, OrderId, OrderNature, + Parameters, Price, }; use state::{LevelView, MatchingEngine, MatchingEngineError}; @@ -56,6 +57,8 @@ impl Contract for MatchingEngineContract { type Storage = ViewStateStorage; type State = MatchingEngine; type Message = Message; + type InitializationArgument = (); + type Parameters = Parameters; async fn new( state: MatchingEngine, diff --git a/examples/matching-engine/src/lib.rs b/examples/matching-engine/src/lib.rs index db3f1f9dd65..d0d4d52a35a 100644 --- a/examples/matching-engine/src/lib.rs +++ b/examples/matching-engine/src/lib.rs @@ -280,14 +280,11 @@ use serde::{Deserialize, Serialize}; pub struct MatchingEngineAbi; impl ContractAbi for MatchingEngineAbi { - type InitializationArgument = (); - type Parameters = Parameters; type Operation = Operation; type Response = (); } impl ServiceAbi for MatchingEngineAbi { - type Parameters = Parameters; type Query = Request; type QueryResponse = Response; } diff --git a/examples/matching-engine/src/service.rs b/examples/matching-engine/src/service.rs index f35ad1bb910..2ab095a0617 100644 --- a/examples/matching-engine/src/service.rs +++ b/examples/matching-engine/src/service.rs @@ -11,7 +11,7 @@ use async_graphql::{EmptySubscription, Request, Response, Schema}; use linera_sdk::{ base::WithServiceAbi, graphql::GraphQLMutationRoot, Service, ServiceRuntime, ViewStateStorage, }; -use matching_engine::Operation; +use matching_engine::{Operation, Parameters}; use crate::state::{MatchingEngine, MatchingEngineError}; @@ -29,6 +29,7 @@ impl Service for MatchingEngineService { type Error = MatchingEngineError; type Storage = ViewStateStorage; type State = MatchingEngine; + type Parameters = Parameters; async fn new(state: Self::State, _runtime: ServiceRuntime) -> Result { Ok(MatchingEngineService { diff --git a/examples/matching-engine/tests/transaction.rs b/examples/matching-engine/tests/transaction.rs index ee5d6f4b80e..2b8c7a632ef 100644 --- a/examples/matching-engine/tests/transaction.rs +++ b/examples/matching-engine/tests/transaction.rs @@ -6,7 +6,6 @@ #![cfg(not(target_arch = "wasm32"))] use async_graphql::InputType; -use fungible::{FungibleTokenAbi, InitialStateBuilder}; use linera_sdk::{ base::{AccountOwner, Amount, ApplicationId, ApplicationPermissions}, test::{ActiveChain, TestValidator}, @@ -67,7 +66,8 @@ pub async fn get_orders( /// * User_b: It has 8 - 3 = 5 token B and the newly acquired 6 token A #[tokio::test] async fn single_transaction() { - let (validator, bytecode_id) = TestValidator::with_current_bytecode().await; + let (validator, bytecode_id) = + TestValidator::with_current_bytecode::().await; let mut user_chain_a = validator.new_chain().await; let owner_a = AccountOwner::from(user_chain_a.public_key()); @@ -76,14 +76,18 @@ async fn single_transaction() { let mut matching_chain = validator.new_chain().await; let admin_account = AccountOwner::from(matching_chain.public_key()); - let fungible_bytecode_id_a = user_chain_a.publish_bytecodes_in("../fungible").await; - let fungible_bytecode_id_b = user_chain_b.publish_bytecodes_in("../fungible").await; + let fungible_bytecode_id_a = user_chain_a + .publish_bytecodes_in::("../fungible") + .await; + let fungible_bytecode_id_b = user_chain_b + .publish_bytecodes_in::("../fungible") + .await; let initial_state_a = - InitialStateBuilder::default().with_account(owner_a, Amount::from_tokens(10)); + fungible::InitialStateBuilder::default().with_account(owner_a, Amount::from_tokens(10)); let params_a = fungible::Parameters::new("A"); let token_id_a = user_chain_a - .create_application::( + .create_application( fungible_bytecode_id_a, params_a, initial_state_a.build(), @@ -91,10 +95,10 @@ async fn single_transaction() { ) .await; let initial_state_b = - InitialStateBuilder::default().with_account(owner_b, Amount::from_tokens(9)); + fungible::InitialStateBuilder::default().with_account(owner_b, Amount::from_tokens(9)); let params_b = fungible::Parameters::new("B"); let token_id_b = user_chain_b - .create_application::( + .create_application( fungible_bytecode_id_b, params_b, initial_state_b.build(), @@ -127,7 +131,7 @@ async fn single_transaction() { let tokens = [token_id_a, token_id_b]; let matching_parameter = Parameters { tokens }; let matching_id = matching_chain - .create_application::( + .create_application( bytecode_id, matching_parameter, (), diff --git a/examples/meta-counter/src/contract.rs b/examples/meta-counter/src/contract.rs index 858c00f241d..4bf7415a7b9 100644 --- a/examples/meta-counter/src/contract.rs +++ b/examples/meta-counter/src/contract.rs @@ -38,6 +38,8 @@ impl Contract for MetaCounterContract { type Storage = SimpleStateStorage; type State = MetaCounter; type Message = Message; + type InitializationArgument = (); + type Parameters = ApplicationId; async fn new(state: MetaCounter, runtime: ContractRuntime) -> Result { Ok(MetaCounterContract { state, runtime }) diff --git a/examples/meta-counter/src/lib.rs b/examples/meta-counter/src/lib.rs index 048a9e6c804..85006e51587 100644 --- a/examples/meta-counter/src/lib.rs +++ b/examples/meta-counter/src/lib.rs @@ -8,14 +8,12 @@ This application is only used for testing cross-application calls. */ use async_graphql::{Request, Response}; -use linera_sdk::base::{ApplicationId, ChainId, ContractAbi, ServiceAbi}; +use linera_sdk::base::{ChainId, ContractAbi, ServiceAbi}; use serde::{Deserialize, Serialize}; pub struct MetaCounterAbi; impl ContractAbi for MetaCounterAbi { - type InitializationArgument = (); - type Parameters = ApplicationId; type Operation = Operation; type Response = (); } @@ -60,5 +58,4 @@ pub enum Message { impl ServiceAbi for MetaCounterAbi { type Query = Request; type QueryResponse = Response; - type Parameters = ApplicationId; } diff --git a/examples/meta-counter/src/service.rs b/examples/meta-counter/src/service.rs index 00f3e108a7e..7e88ca3b519 100644 --- a/examples/meta-counter/src/service.rs +++ b/examples/meta-counter/src/service.rs @@ -6,7 +6,10 @@ mod state; use async_graphql::{Request, Response}; -use linera_sdk::{base::WithServiceAbi, Service, ServiceRuntime, SimpleStateStorage}; +use linera_sdk::{ + base::{ApplicationId, WithServiceAbi}, + Service, ServiceRuntime, SimpleStateStorage, +}; use thiserror::Error; use self::state::MetaCounter; @@ -25,6 +28,7 @@ impl Service for MetaCounterService { type Error = Error; type Storage = SimpleStateStorage; type State = MetaCounter; + type Parameters = ApplicationId; async fn new(_state: Self::State, runtime: ServiceRuntime) -> Result { Ok(MetaCounterService { runtime }) diff --git a/examples/native-fungible/src/contract.rs b/examples/native-fungible/src/contract.rs index bd1312f1dd4..5005d4079b5 100644 --- a/examples/native-fungible/src/contract.rs +++ b/examples/native-fungible/src/contract.rs @@ -6,7 +6,7 @@ mod state; use async_trait::async_trait; -use fungible::{FungibleResponse, FungibleTokenAbi, Operation}; +use fungible::{FungibleResponse, FungibleTokenAbi, InitialState, Operation, Parameters}; use linera_sdk::{ base::{Account, AccountOwner, ChainId, Owner, WithContractAbi}, ensure, Contract, ContractRuntime, ViewStateStorage, @@ -33,6 +33,8 @@ impl Contract for NativeFungibleTokenContract { type Storage = ViewStateStorage; type State = NativeFungibleToken; type Message = Message; + type Parameters = Parameters; + type InitializationArgument = InitialState; async fn new( state: NativeFungibleToken, diff --git a/examples/native-fungible/src/service.rs b/examples/native-fungible/src/service.rs index 97b53983819..94222e636ea 100644 --- a/examples/native-fungible/src/service.rs +++ b/examples/native-fungible/src/service.rs @@ -8,7 +8,7 @@ mod state; use std::sync::{Arc, Mutex}; use async_graphql::{EmptySubscription, Object, Request, Response, Schema}; -use fungible::Operation; +use fungible::{Operation, Parameters}; use linera_sdk::{ base::{AccountOwner, WithServiceAbi}, graphql::GraphQLMutationRoot, @@ -34,6 +34,7 @@ impl Service for NativeFungibleTokenService { type Error = Error; type Storage = ViewStateStorage; type State = NativeFungibleToken; + type Parameters = Parameters; async fn new(_state: Self::State, runtime: ServiceRuntime) -> Result { Ok(NativeFungibleTokenService { diff --git a/examples/non-fungible/src/contract.rs b/examples/non-fungible/src/contract.rs index 99e90d9737b..44f4804cef9 100644 --- a/examples/non-fungible/src/contract.rs +++ b/examples/non-fungible/src/contract.rs @@ -35,6 +35,8 @@ impl Contract for NonFungibleTokenContract { type Storage = ViewStateStorage; type State = NonFungibleToken; type Message = Message; + type InitializationArgument = (); + type Parameters = (); async fn new( state: NonFungibleToken, diff --git a/examples/non-fungible/src/lib.rs b/examples/non-fungible/src/lib.rs index 378b0d31c81..3b941a61136 100644 --- a/examples/non-fungible/src/lib.rs +++ b/examples/non-fungible/src/lib.rs @@ -177,8 +177,6 @@ pub struct TokenId { pub struct NonFungibleTokenAbi; impl ContractAbi for NonFungibleTokenAbi { - type InitializationArgument = (); - type Parameters = (); type Operation = Operation; type Response = (); } @@ -186,7 +184,6 @@ impl ContractAbi for NonFungibleTokenAbi { impl ServiceAbi for NonFungibleTokenAbi { type Query = Request; type QueryResponse = Response; - type Parameters = (); } /// An operation. diff --git a/examples/non-fungible/src/service.rs b/examples/non-fungible/src/service.rs index 7e5cb712447..43459a1e119 100644 --- a/examples/non-fungible/src/service.rs +++ b/examples/non-fungible/src/service.rs @@ -36,6 +36,7 @@ impl Service for NonFungibleTokenService { type Error = Error; type Storage = ViewStateStorage; type State = NonFungibleToken; + type Parameters = (); async fn new(state: Self::State, _runtime: ServiceRuntime) -> Result { Ok(NonFungibleTokenService { diff --git a/examples/social/src/contract.rs b/examples/social/src/contract.rs index 08a21721c59..055dcb4cbfa 100644 --- a/examples/social/src/contract.rs +++ b/examples/social/src/contract.rs @@ -37,6 +37,8 @@ impl Contract for SocialContract { type Storage = ViewStateStorage; type State = Social; type Message = Message; + type InitializationArgument = (); + type Parameters = (); async fn new(state: Social, runtime: ContractRuntime) -> Result { Ok(SocialContract { state, runtime }) diff --git a/examples/social/src/lib.rs b/examples/social/src/lib.rs index 540602b9c74..ca2070e1f3b 100644 --- a/examples/social/src/lib.rs +++ b/examples/social/src/lib.rs @@ -182,8 +182,6 @@ use serde::{Deserialize, Serialize}; pub struct SocialAbi; impl ContractAbi for SocialAbi { - type InitializationArgument = (); - type Parameters = (); type Operation = Operation; type Response = (); } @@ -191,7 +189,6 @@ impl ContractAbi for SocialAbi { impl ServiceAbi for SocialAbi { type Query = Request; type QueryResponse = Response; - type Parameters = (); } /// An operation that can be executed by the application. diff --git a/examples/social/src/service.rs b/examples/social/src/service.rs index 2a02470ba3f..01810c5f1b6 100644 --- a/examples/social/src/service.rs +++ b/examples/social/src/service.rs @@ -30,6 +30,7 @@ impl Service for SocialService { type Error = Error; type Storage = ViewStateStorage; type State = Social; + type Parameters = (); async fn new(state: Self::State, _runtime: ServiceRuntime) -> Result { Ok(SocialService { diff --git a/examples/social/tests/cross_chain.rs b/examples/social/tests/cross_chain.rs index 75f1a17bf63..b88d99f98a7 100644 --- a/examples/social/tests/cross_chain.rs +++ b/examples/social/tests/cross_chain.rs @@ -14,13 +14,12 @@ use social::Operation; /// send a message to chain2 and see it received on chain1. #[tokio::test] async fn test_cross_chain_posting() { - let (validator, bytecode_id) = TestValidator::with_current_bytecode().await; + let (validator, bytecode_id) = + TestValidator::with_current_bytecode::().await; let mut chain1 = validator.new_chain().await; // Initialization is trivial for the social app - let application_id = chain1 - .create_application::(bytecode_id, (), (), vec![]) - .await; + let application_id = chain1.create_application(bytecode_id, (), (), vec![]).await; let chain2 = validator.new_chain().await; diff --git a/linera-base/src/abi.rs b/linera-base/src/abi.rs index 976d85285dc..00f3723f9e9 100644 --- a/linera-base/src/abi.rs +++ b/linera-base/src/abi.rs @@ -15,21 +15,11 @@ pub trait Abi: ContractAbi + ServiceAbi {} // ANCHOR_END: abi // T::Parameters is duplicated for simplicity but it must match. -impl Abi for T where T: ContractAbi + ServiceAbi::Parameters> {} +impl Abi for T where T: ContractAbi + ServiceAbi {} // ANCHOR: contract_abi /// A trait that includes all the types exported by a Linera application contract. pub trait ContractAbi { - /// Immutable parameters specific to this application (e.g. the name of a token). - type Parameters: Serialize + DeserializeOwned + Send + Sync + Clone + Debug + 'static; - - /// Initialization argument passed to a new application on the chain that created it - /// (e.g. an initial amount of tokens minted). - /// - /// To share configuration data on every chain, use [`ContractAbi::Parameters`] - /// instead. - type InitializationArgument: Serialize + DeserializeOwned + Send + Sync + Debug + 'static; - /// The type of operation executed by the application. /// /// Operations are transactions directly added to a block by the creator (and signer) @@ -45,9 +35,6 @@ pub trait ContractAbi { // ANCHOR: service_abi /// A trait that includes all the types exported by a Linera application service. pub trait ServiceAbi { - /// Immutable parameters specific to this application (e.g. the name of a token). - type Parameters: Serialize + DeserializeOwned + Send + Sync + Clone + Debug + 'static; - /// The type of a query receivable by the application's service. type Query: Serialize + DeserializeOwned + Send + Sync + Debug + 'static; @@ -66,9 +53,6 @@ impl ContractAbi for A where A: WithContractAbi, { - type InitializationArgument = - <::Abi as ContractAbi>::InitializationArgument; - type Parameters = <::Abi as ContractAbi>::Parameters; type Operation = <::Abi as ContractAbi>::Operation; type Response = <::Abi as ContractAbi>::Response; } @@ -85,5 +69,4 @@ where { type Query = <::Abi as ServiceAbi>::Query; type QueryResponse = <::Abi as ServiceAbi>::QueryResponse; - type Parameters = <::Abi as ServiceAbi>::Parameters; } diff --git a/linera-base/src/identifiers.rs b/linera-base/src/identifiers.rs index 24d8e3a0fb8..6dae8055648 100644 --- a/linera-base/src/identifiers.rs +++ b/linera-base/src/identifiers.rs @@ -161,10 +161,10 @@ impl From for GenericApplicationId { /// A unique identifier for an application bytecode. #[cfg_attr(with_testing, derive(Default))] -pub struct BytecodeId { +pub struct BytecodeId { /// The message ID that published the bytecode. pub message_id: MessageId, - _phantom: std::marker::PhantomData, + _phantom: std::marker::PhantomData<(Abi, Parameters, InitializationArgument)>, } /// The name of a subscription channel. @@ -219,15 +219,22 @@ impl ChannelName { } // Cannot use #[derive(Clone)] because it requires `A: Clone`. -impl Clone for BytecodeId { +impl Clone + for BytecodeId +{ fn clone(&self) -> Self { *self } } -impl Copy for BytecodeId {} +impl Copy + for BytecodeId +{ +} -impl PartialEq for BytecodeId { +impl PartialEq + for BytecodeId +{ fn eq(&self, other: &Self) -> bool { let BytecodeId { message_id, @@ -237,9 +244,14 @@ impl PartialEq for BytecodeId { } } -impl Eq for BytecodeId {} +impl Eq + for BytecodeId +{ +} -impl PartialOrd for BytecodeId { +impl PartialOrd + for BytecodeId +{ fn partial_cmp(&self, other: &Self) -> Option { let BytecodeId { message_id, @@ -249,7 +261,9 @@ impl PartialOrd for BytecodeId { } } -impl Ord for BytecodeId { +impl Ord + for BytecodeId +{ fn cmp(&self, other: &Self) -> std::cmp::Ordering { let BytecodeId { message_id, @@ -259,7 +273,9 @@ impl Ord for BytecodeId { } } -impl Hash for BytecodeId { +impl Hash + for BytecodeId +{ fn hash(&self, state: &mut H) { let BytecodeId { message_id, @@ -269,7 +285,9 @@ impl Hash for BytecodeId { } } -impl Debug for BytecodeId { +impl Debug + for BytecodeId +{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let BytecodeId { message_id, @@ -287,7 +305,9 @@ struct SerializableBytecodeId { message_id: MessageId, } -impl Serialize for BytecodeId { +impl Serialize + for BytecodeId +{ fn serialize(&self, serializer: S) -> Result where S: serde::ser::Serializer, @@ -306,7 +326,9 @@ impl Serialize for BytecodeId { } } -impl<'de, A> Deserialize<'de> for BytecodeId { +impl<'de, Abi, Parameters, InitializationArgument> Deserialize<'de> + for BytecodeId +{ fn deserialize(deserializer: D) -> Result where D: serde::de::Deserializer<'de>, @@ -340,7 +362,9 @@ impl BytecodeId { } /// Specializes a bytecode ID for a given ABI. - pub fn with_abi(self) -> BytecodeId { + pub fn with_abi( + self, + ) -> BytecodeId { BytecodeId { message_id: self.message_id, _phantom: std::marker::PhantomData, @@ -348,7 +372,7 @@ impl BytecodeId { } } -impl BytecodeId { +impl BytecodeId { /// Forgets the ABI of a bytecode ID (if any). pub fn forget_abi(self) -> BytecodeId { BytecodeId { @@ -356,6 +380,14 @@ impl BytecodeId { _phantom: std::marker::PhantomData, } } + + /// Leaves just the ABI of a bytecode ID (if any). + pub fn just_abi(self) -> BytecodeId { + BytecodeId { + message_id: self.message_id, + _phantom: std::marker::PhantomData, + } + } } // Cannot use #[derive(Clone)] because it requires `A: Clone`. diff --git a/linera-core/src/client.rs b/linera-core/src/client.rs index c9016604730..e755023ce40 100644 --- a/linera-core/src/client.rs +++ b/linera-core/src/client.rs @@ -17,7 +17,7 @@ use futures::{ stream::{self, AbortHandle, FuturesUnordered, StreamExt}, }; use linera_base::{ - abi::{Abi, ContractAbi}, + abi::Abi, crypto::{CryptoHash, KeyPair, PublicKey}, data_types::{Amount, ApplicationPermissions, ArithmeticError, BlockHeight, Round, Timestamp}, ensure, @@ -43,6 +43,7 @@ use linera_execution::{ use linera_storage::Storage; use linera_views::views::ViewError; use lru::LruCache; +use serde::Serialize; use thiserror::Error; use tracing::{debug, error, info}; @@ -1810,11 +1811,15 @@ where } /// Creates an application by instantiating some bytecode. - pub async fn create_application( + pub async fn create_application< + A: Abi, + Parameters: Serialize, + InitializationArgument: Serialize, + >( &mut self, - bytecode_id: BytecodeId, - parameters: &::Parameters, - initialization_argument: &A::InitializationArgument, + bytecode_id: BytecodeId, + parameters: &Parameters, + initialization_argument: &InitializationArgument, required_application_ids: Vec, ) -> Result, Certificate)>, ChainClientError> { let initialization_argument = serde_json::to_vec(initialization_argument)?; diff --git a/linera-core/src/unit_tests/wasm_client_tests.rs b/linera-core/src/unit_tests/wasm_client_tests.rs index c9e20b1452b..dc5a1e665ac 100644 --- a/linera-core/src/unit_tests/wasm_client_tests.rs +++ b/linera-core/src/unit_tests/wasm_client_tests.rs @@ -16,9 +16,10 @@ use std::collections::BTreeMap; use assert_matches::assert_matches; use async_graphql::Request; +use counter::CounterAbi; use linera_base::{ data_types::Amount, - identifiers::{AccountOwner, ChainDescription, ChainId, Destination, Owner}, + identifiers::{AccountOwner, ApplicationId, ChainDescription, ChainId, Destination, Owner}, }; use linera_chain::data_types::{CertificateValue, MessageAction, OutgoingMessage}; use linera_execution::{ @@ -121,7 +122,7 @@ where .await .unwrap() .unwrap(); - let bytecode_id = bytecode_id.with_abi::(); + let bytecode_id = bytecode_id.with_abi::(); // Receive our own cert to broadcast the bytecode location. publisher.receive_certificate(cert).await.unwrap(); publisher.process_inbox().await.unwrap(); @@ -274,7 +275,7 @@ where .unwrap() .unwrap() }; - let bytecode_id1 = bytecode_id1.with_abi::(); + let bytecode_id1 = bytecode_id1.with_abi::(); let (bytecode_id2, cert2) = { let (contract_path, service_path) = linera_execution::wasm_test::get_example_bytecode_paths("meta_counter")?; @@ -287,7 +288,8 @@ where .unwrap() .unwrap() }; - let bytecode_id2 = bytecode_id2.with_abi::(); + let bytecode_id2 = + bytecode_id2.with_abi::, ()>(); // Receive our own certs to broadcast the bytecode locations. publisher.receive_certificate(cert1).await.unwrap(); publisher.receive_certificate(cert2).await.unwrap(); @@ -476,7 +478,8 @@ where .unwrap() .unwrap() }; - let bytecode_id = bytecode_id.with_abi::(); + let bytecode_id = bytecode_id + .with_abi::(); // Receive our own cert to broadcast the bytecode location. sender.receive_certificate(pub_cert.clone()).await.unwrap(); @@ -695,7 +698,7 @@ where .unwrap() .unwrap() }; - let bytecode_id = bytecode_id.with_abi::(); + let bytecode_id = bytecode_id.with_abi::(); // Receive our own cert to broadcast the bytecode location. receiver diff --git a/linera-sdk/src/abis/fungible.rs b/linera-sdk/src/abis/fungible.rs index 9cdff3e0e6e..2c65e7b6480 100644 --- a/linera-sdk/src/abis/fungible.rs +++ b/linera-sdk/src/abis/fungible.rs @@ -18,8 +18,6 @@ use serde::{Deserialize, Serialize}; pub struct FungibleTokenAbi; impl ContractAbi for FungibleTokenAbi { - type InitializationArgument = InitialState; - type Parameters = Parameters; type Operation = Operation; type Response = FungibleResponse; } @@ -27,7 +25,6 @@ impl ContractAbi for FungibleTokenAbi { impl ServiceAbi for FungibleTokenAbi { type Query = Request; type QueryResponse = Response; - type Parameters = Parameters; } /// An operation diff --git a/linera-sdk/src/contract/runtime.rs b/linera-sdk/src/contract/runtime.rs index c198673da33..979584a4d9a 100644 --- a/linera-sdk/src/contract/runtime.rs +++ b/linera-sdk/src/contract/runtime.rs @@ -22,7 +22,7 @@ pub struct ContractRuntime where Application: Contract, { - application_parameters: Option<::Parameters>, + application_parameters: Option, application_id: Option>, chain_id: Option, authenticated_signer: Option>, @@ -53,7 +53,7 @@ where } /// Returns the application parameters provided when the application was created. - pub fn application_parameters(&mut self) -> ::Parameters { + pub fn application_parameters(&mut self) -> Application::Parameters { self.application_parameters .get_or_insert_with(|| { let bytes = wit::application_parameters(); diff --git a/linera-sdk/src/lib.rs b/linera-sdk/src/lib.rs index bbc7d5ce1d5..485d0bbf127 100644 --- a/linera-sdk/src/lib.rs +++ b/linera-sdk/src/lib.rs @@ -114,6 +114,16 @@ pub trait Contract: WithContractAbi + ContractAbi + Send + Sized { /// from another chain and accepted in a block. type Message: Serialize + DeserializeOwned + Send + Sync + Debug + 'static; + /// Immutable parameters specific to this application (e.g. the name of a token). + type Parameters: Serialize + DeserializeOwned + Send + Sync + Clone + Debug + 'static; + + /// Initialization argument passed to a new application on the chain that created it + /// (e.g. an initial amount of tokens minted). + /// + /// To share configuration data on every chain, use [`Contract::Parameters`] + /// instead. + type InitializationArgument: Serialize + DeserializeOwned + Send + Sync + Debug + 'static; + /// Creates a in-memory instance of the contract handler from the application's `state`. async fn new(state: Self::State, runtime: ContractRuntime) -> Result; @@ -187,6 +197,9 @@ pub trait Service: WithServiceAbi + ServiceAbi + Sized { /// Storage = SimpleStateStorage` or `type Storage = ViewStateStorage`. type Storage: ServiceStateStorage; + /// Immutable parameters specific to this application. + type Parameters: Serialize + DeserializeOwned + Send + Sync + Clone + Debug + 'static; + /// Creates a in-memory instance of the service handler from the application's `state`. async fn new(state: Self::State, runtime: ServiceRuntime) -> Result; diff --git a/linera-sdk/src/service/runtime.rs b/linera-sdk/src/service/runtime.rs index a350c5e89ad..ff8c0f9844e 100644 --- a/linera-sdk/src/service/runtime.rs +++ b/linera-sdk/src/service/runtime.rs @@ -19,7 +19,7 @@ pub struct ServiceRuntime where Application: Service, { - application_parameters: Cell::Parameters>>, + application_parameters: Cell>, application_id: Cell>>, chain_id: Cell>, next_block_height: Cell>, @@ -48,7 +48,7 @@ where } /// Returns the application parameters provided when the application was created. - pub fn application_parameters(&self) -> ::Parameters { + pub fn application_parameters(&self) -> Application::Parameters { Self::fetch_value_through_cache(&self.application_parameters, || { let bytes = wit::application_parameters(); serde_json::from_slice(&bytes).expect("Application parameters must be deserializable") diff --git a/linera-sdk/src/test/integration/chain.rs b/linera-sdk/src/test/integration/chain.rs index 411db43966b..0dd43339e2c 100644 --- a/linera-sdk/src/test/integration/chain.rs +++ b/linera-sdk/src/test/integration/chain.rs @@ -23,6 +23,7 @@ use linera_execution::{ system::{SystemChannel, SystemExecutionError, SystemMessage, SystemOperation}, Bytecode, Message, Query, Response, }; +use serde::Serialize; use tokio::{fs, sync::Mutex}; use super::{BlockBuilder, TestValidator}; @@ -127,7 +128,9 @@ impl ActiveChain { /// Searches the Cargo manifest for binaries that end with `contract` and `service`, builds /// them for WebAssembly and uses the generated binaries as the contract and service bytecodes /// to be published on this chain. Returns the bytecode ID to reference the published bytecode. - pub async fn publish_current_bytecode(&self) -> BytecodeId { + pub async fn publish_current_bytecode( + &self, + ) -> BytecodeId { self.publish_bytecodes_in(".").await } @@ -136,10 +139,10 @@ impl ActiveChain { /// Searches the Cargo manifest for binaries that end with `contract` and `service`, builds /// them for WebAssembly and uses the generated binaries as the contract and service bytecodes /// to be published on this chain. Returns the bytecode ID to reference the published bytecode. - pub async fn publish_bytecodes_in( + pub async fn publish_bytecodes_in( &self, repository_path: impl AsRef, - ) -> BytecodeId { + ) -> BytecodeId { let repository_path = fs::canonicalize(repository_path) .await .expect("Failed to obtain absolute application repository path"); @@ -300,15 +303,17 @@ impl ActiveChain { /// The application is initialized using the initialization parameters, which consist of the /// global static `parameters`, the one time `initialization_argument` and the /// `required_application_ids` of the applications that the new application will depend on. - pub async fn create_application( + pub async fn create_application( &mut self, - bytecode_id: BytecodeId, - parameters: A::Parameters, - initialization_argument: A::InitializationArgument, + bytecode_id: BytecodeId, + parameters: Parameters, + initialization_argument: InitializationArgument, required_application_ids: Vec, - ) -> ApplicationId + ) -> ApplicationId where - A: ContractAbi, + Abi: ContractAbi, + Parameters: Serialize, + InitializationArgument: Serialize, { let bytecode_location_message = if self.needs_bytecode_location(bytecode_id).await { self.subscribe_to_published_bytecodes_from(bytecode_id.message_id.chain_id) @@ -343,13 +348,16 @@ impl ActiveChain { assert_eq!(creation_messages.len(), 1); ApplicationId { - bytecode_id, + bytecode_id: bytecode_id.just_abi(), creation: creation_messages[0], } } /// Checks if the `bytecode_id` is missing from this microchain. - async fn needs_bytecode_location(&self, bytecode_id: BytecodeId) -> bool { + async fn needs_bytecode_location( + &self, + bytecode_id: BytecodeId, + ) -> bool { let applications = self .validator .worker() @@ -366,7 +374,10 @@ impl ActiveChain { } /// Finds the message that sends the message with the bytecode location of `bytecode_id`. - async fn find_bytecode_location(&self, bytecode_id: BytecodeId) -> MessageId { + async fn find_bytecode_location( + &self, + bytecode_id: BytecodeId, + ) -> MessageId { for height in bytecode_id.message_id.height.0.. { let certificate = self .validator diff --git a/linera-sdk/src/test/integration/validator.rs b/linera-sdk/src/test/integration/validator.rs index 60ad23cc061..4f0390a3ef5 100644 --- a/linera-sdk/src/test/integration/validator.rs +++ b/linera-sdk/src/test/integration/validator.rs @@ -25,6 +25,7 @@ use linera_execution::{ }; use linera_storage::{MemoryStorage, Storage, WallClock}; use linera_views::memory::{MemoryStoreConfig, TEST_MEMORY_MAX_STREAM_QUERIES}; +use serde::Serialize; use tokio::sync::{Mutex, MutexGuard}; use super::ActiveChain; @@ -93,7 +94,10 @@ impl TestValidator { /// calling this method published on it. /// /// Returns the new [`TestValidator`] and the [`BytecodeId`] of the published bytecode. - pub async fn with_current_bytecode() -> (TestValidator, BytecodeId) { + pub async fn with_current_bytecode() -> ( + TestValidator, + BytecodeId, + ) { let validator = TestValidator::default(); let publisher = validator.new_chain().await; @@ -109,19 +113,22 @@ impl TestValidator { /// another microchain. /// /// Returns the new [`TestValidator`] and the [`ApplicationId`] of the created application. - pub async fn with_current_application( - parameters: A::Parameters, - initialization_argument: A::InitializationArgument, - ) -> (TestValidator, ApplicationId) + pub async fn with_current_application( + parameters: Parameters, + initialization_argument: InitializationArgument, + ) -> (TestValidator, ApplicationId) where - A: ContractAbi, + Abi: ContractAbi, + Parameters: Serialize, + InitializationArgument: Serialize, { - let (validator, bytecode_id) = TestValidator::with_current_bytecode().await; + let (validator, bytecode_id) = + TestValidator::with_current_bytecode::().await; let mut creator = validator.new_chain().await; let application_id = creator - .create_application::(bytecode_id, parameters, initialization_argument, vec![]) + .create_application(bytecode_id, parameters, initialization_argument, vec![]) .await; (validator, application_id) diff --git a/linera-sdk/wasm-tests/src/lib.rs b/linera-sdk/wasm-tests/src/lib.rs index d7b6e3c603f..e4afb829a55 100644 --- a/linera-sdk/wasm-tests/src/lib.rs +++ b/linera-sdk/wasm-tests/src/lib.rs @@ -385,14 +385,11 @@ fn mock_query() { pub struct Abi; impl ContractAbi for Abi { - type Parameters = Vec; - type InitializationArgument = Vec; type Operation = Vec; type Response = Vec; } impl ServiceAbi for Abi { - type Parameters = Vec; type Query = Vec; type QueryResponse = Vec; } @@ -415,6 +412,8 @@ impl Contract for TestApp { type Storage = SimpleStateStorage; type State = (); type Message = Vec; + type Parameters = Vec; + type InitializationArgument = Vec; async fn new(state: (), _runtime: ContractRuntime) -> Result { Ok(TestApp { state }) @@ -447,6 +446,7 @@ impl Service for TestApp { type Error = TestAppError; type Storage = SimpleStateStorage; type State = (); + type Parameters = Vec; async fn new(state: (), _runtime: ServiceRuntime) -> Result { Ok(TestApp { state }) diff --git a/linera-service-graphql-client/tests/test.rs b/linera-service-graphql-client/tests/test.rs index 3acced2d128..9b2ba57d0b2 100644 --- a/linera-service-graphql-client/tests/test.rs +++ b/linera-service-graphql-client/tests/test.rs @@ -62,7 +62,14 @@ async fn test_end_to_end_queries(config: impl LineraNetConfig) { }; let params = fungible::Parameters::new("FUN"); let application_id = client - .publish_and_create::(contract, service, ¶ms, &state, &[], None) + .publish_and_create::( + contract, + service, + ¶ms, + &state, + &[], + None, + ) .await .unwrap(); diff --git a/linera-service/src/benchmark.rs b/linera-service/src/benchmark.rs index 7b7881f3c50..695a182e2aa 100644 --- a/linera-service/src/benchmark.rs +++ b/linera-service/src/benchmark.rs @@ -133,7 +133,9 @@ async fn benchmark_with_fungible( let (contract, service) = publisher.build_application(&path, "fungible", true).await?; info!("Publishing the fungible application bytecode."); - let bytecode_id = publisher.publish_bytecode(contract, service, None).await?; + let bytecode_id = publisher + .publish_bytecode::(contract, service, None) + .await?; struct BenchmarkContext { application_id: ApplicationId, @@ -154,7 +156,7 @@ async fn benchmark_with_fungible( }; let parameters = Parameters::new(format!("FUN{}", i).leak()); let application_id = node_service - .create_application::( + .create_application( &default_chain, &bytecode_id, ¶meters, diff --git a/linera-service/src/cli_wrappers/wallet.rs b/linera-service/src/cli_wrappers/wallet.rs index d61ca3ab1ed..d5bca619e4c 100644 --- a/linera-service/src/cli_wrappers/wallet.rs +++ b/linera-service/src/cli_wrappers/wallet.rs @@ -255,12 +255,16 @@ impl ClientWrapper { } /// Runs `linera wallet publish-and-create`. - pub async fn publish_and_create( + pub async fn publish_and_create< + A: ContractAbi, + Parameters: Serialize, + InitializationArgument: Serialize, + >( &self, contract: PathBuf, service: PathBuf, - parameters: &A::Parameters, - argument: &A::InitializationArgument, + parameters: &Parameters, + argument: &InitializationArgument, required_application_ids: &[ApplicationId], publisher: impl Into>, ) -> Result> { @@ -286,12 +290,12 @@ impl ClientWrapper { } /// Runs `linera publish-bytecode`. - pub async fn publish_bytecode( + pub async fn publish_bytecode( &self, contract: PathBuf, service: PathBuf, publisher: impl Into>, - ) -> Result { + ) -> Result> { let stdout = self .command() .await? @@ -300,24 +304,29 @@ impl ClientWrapper { .args(publisher.into().iter().map(ChainId::to_string)) .spawn_and_wait_for_stdout() .await?; - Ok(stdout.trim().parse()?) + let bytecode_id: BytecodeId = stdout.trim().parse()?; + Ok(bytecode_id.with_abi()) } /// Runs `linera create-application`. - pub async fn create_application( + pub async fn create_application< + Abi: ContractAbi, + Parameters: Serialize, + InitializationArgument: Serialize, + >( &self, - bytecode_id: &BytecodeId, - parameters: &A::Parameters, - argument: &A::InitializationArgument, + bytecode_id: &BytecodeId, + parameters: &Parameters, + argument: &InitializationArgument, required_application_ids: &[ApplicationId], creator: impl Into>, - ) -> Result> { + ) -> Result> { let json_parameters = serde_json::to_string(parameters)?; let json_argument = serde_json::to_string(argument)?; let mut command = self.command().await?; command .arg("create-application") - .arg(bytecode_id.to_string()) + .arg(bytecode_id.forget_abi().to_string()) .args(["--json-parameters", &json_parameters]) .args(["--json-argument", &json_argument]) .args(creator.into().iter().map(ChainId::to_string)); @@ -876,12 +885,12 @@ impl NodeService { .collect() } - pub async fn publish_bytecode( + pub async fn publish_bytecode( &self, chain_id: &ChainId, contract: PathBuf, service: PathBuf, - ) -> Result { + ) -> Result> { let contract_code = Bytecode::load_from_file(&contract).await?; let service_code = Bytecode::load_from_file(&service).await?; let query = format!( @@ -894,7 +903,10 @@ impl NodeService { let bytecode_str = data["publishBytecode"] .as_str() .context("bytecode ID not found")?; - bytecode_str.parse().context("could not parse bytecode ID") + let bytecode_id: BytecodeId = bytecode_str + .parse() + .context("could not parse bytecode ID")?; + Ok(bytecode_id.with_abi()) } pub async fn query_node(&self, query: impl AsRef) -> Result { @@ -937,14 +949,19 @@ impl NodeService { ); } - pub async fn create_application( + pub async fn create_application< + Abi: ContractAbi, + Parameters: Serialize, + InitializationArgument: Serialize, + >( &self, chain_id: &ChainId, - bytecode_id: &BytecodeId, - parameters: &A::Parameters, - argument: &A::InitializationArgument, + bytecode_id: &BytecodeId, + parameters: &Parameters, + argument: &InitializationArgument, required_application_ids: &[ApplicationId], - ) -> Result> { + ) -> Result> { + let bytecode_id = bytecode_id.forget_abi(); let json_required_applications_ids = required_application_ids .iter() .map(ApplicationId::to_string) diff --git a/linera-service/template/contract.rs.template b/linera-service/template/contract.rs.template index 90e96a02c06..fa628607147 100644 --- a/linera-service/template/contract.rs.template +++ b/linera-service/template/contract.rs.template @@ -25,6 +25,8 @@ impl Contract for ApplicationContract {{ type Storage = ViewStateStorage; type State = Application; type Message = (); + type Parameters = (); + type InitializationArgument = (); async fn new(state: Self::State, runtime: ContractRuntime) -> Result {{ Ok(ApplicationContract {{ state, runtime }}) diff --git a/linera-service/template/lib.rs.template b/linera-service/template/lib.rs.template index 0f3147f62d4..86a60e332b5 100644 --- a/linera-service/template/lib.rs.template +++ b/linera-service/template/lib.rs.template @@ -3,14 +3,11 @@ use linera_sdk::base::{ContractAbi, ServiceAbi}; pub struct ApplicationAbi; impl ContractAbi for ApplicationAbi { - type Parameters = (); - type InitializationArgument = (); type Operation = (); type Response = (); } impl ServiceAbi for ApplicationAbi { - type Parameters = (); type Query = (); type QueryResponse = (); } diff --git a/linera-service/template/service.rs.template b/linera-service/template/service.rs.template index f2cdc7688b2..58b6faeda1f 100644 --- a/linera-service/template/service.rs.template +++ b/linera-service/template/service.rs.template @@ -21,6 +21,7 @@ impl Service for ApplicationService {{ type Error = ServiceError; type Storage = ViewStateStorage; type State = Application; + type Parameters = (); async fn new(state: Self::State, runtime: ServiceRuntime) -> Result {{ Ok(ApplicationService {{ state, runtime }}) diff --git a/linera-service/tests/end_to_end_tests.rs b/linera-service/tests/end_to_end_tests.rs index 91048630bf1..35c61de8510 100644 --- a/linera-service/tests/end_to_end_tests.rs +++ b/linera-service/tests/end_to_end_tests.rs @@ -292,7 +292,7 @@ async fn test_wasm_end_to_end_counter(config: impl LineraNetConfig) { let (contract, service) = client.build_example("counter").await.unwrap(); let application_id = client - .publish_and_create::( + .publish_and_create::( contract, service, &(), @@ -344,11 +344,11 @@ async fn test_wasm_end_to_end_counter_publish_create(config: impl LineraNetConfi let (contract, service) = client.build_example("counter").await.unwrap(); let bytecode_id = client - .publish_bytecode(contract, service, None) + .publish_bytecode::(contract, service, None) .await .unwrap(); let application_id = client - .create_application::(&bytecode_id, &(), &original_counter_value, &[], None) + .create_application(&bytecode_id, &(), &original_counter_value, &[], None) .await .unwrap(); let mut node_service = client.run_node_service(None).await.unwrap(); @@ -395,11 +395,11 @@ async fn test_wasm_end_to_end_social_user_pub_sub(config: impl LineraNetConfig) .unwrap(); let (contract, service) = client1.build_example("social").await.unwrap(); let bytecode_id = client1 - .publish_bytecode(contract, service, None) + .publish_bytecode::(contract, service, None) .await .unwrap(); let application_id = client1 - .create_application::(&bytecode_id, &(), &(), &[], None) + .create_application(&bytecode_id, &(), &(), &[], None) .await .unwrap(); @@ -480,7 +480,7 @@ async fn test_wasm_end_to_end_social_user_pub_sub(config: impl LineraNetConfig) #[cfg_attr(feature = "remote_net", test_case(RemoteNetTestingConfig::new(None), "native-fungible" ; "native_remote_net_grpc"))] #[test_log::test(tokio::test)] async fn test_wasm_end_to_end_fungible(config: impl LineraNetConfig, example_name: &str) { - use fungible::{FungibleTokenAbi, InitialState}; + use fungible::{FungibleTokenAbi, InitialState, Parameters}; let _guard = INTEGRATION_TEST_GUARD.lock().await; @@ -508,12 +508,19 @@ async fn test_wasm_end_to_end_fungible(config: impl LineraNetConfig, example_nam let (contract, service) = client1.build_example(example_name).await.unwrap(); let params = if example_name == "native-fungible" { // Native Fungible has a fixed NAT ticker symbol, anything else will be rejected - fungible::Parameters::new("NAT") + Parameters::new("NAT") } else { - fungible::Parameters::new("FUN") + Parameters::new("FUN") }; let application_id = client1 - .publish_and_create::(contract, service, ¶ms, &state, &[], None) + .publish_and_create::( + contract, + service, + ¶ms, + &state, + &[], + None, + ) .await .unwrap(); @@ -630,7 +637,7 @@ async fn test_wasm_end_to_end_same_wallet_fungible( config: impl LineraNetConfig, example_name: &str, ) { - use fungible::{FungibleTokenAbi, InitialState}; + use fungible::{Account, FungibleTokenAbi, InitialState, Parameters}; let _guard = INTEGRATION_TEST_GUARD.lock().await; let (mut net, client1) = config.instantiate().await.unwrap(); @@ -663,12 +670,19 @@ async fn test_wasm_end_to_end_same_wallet_fungible( let (contract, service) = client1.build_example(example_name).await.unwrap(); let params = if example_name == "native-fungible" { // Native Fungible has a fixed NAT ticker symbol, anything else will be rejected - fungible::Parameters::new("NAT") + Parameters::new("NAT") } else { - fungible::Parameters::new("FUN") + Parameters::new("FUN") }; let application_id = client1 - .publish_and_create::(contract, service, ¶ms, &state, &[], None) + .publish_and_create::( + contract, + service, + ¶ms, + &state, + &[], + None, + ) .await .unwrap(); @@ -692,7 +706,7 @@ async fn test_wasm_end_to_end_same_wallet_fungible( app1.transfer( &account_owner1, Amount::ONE, - fungible::Account { + Account { chain_id: chain2, owner: account_owner2, }, @@ -755,7 +769,7 @@ async fn test_wasm_end_to_end_non_fungible(config: impl LineraNetConfig) { // Setting up the application and verifying let (contract, service) = client1.build_example("non-fungible").await.unwrap(); let application_id = client1 - .publish_and_create::(contract, service, &(), &(), &[], None) + .publish_and_create::(contract, service, &(), &(), &[], None) .await .unwrap(); @@ -1009,7 +1023,7 @@ async fn test_wasm_end_to_end_non_fungible(config: impl LineraNetConfig) { #[test_log::test(tokio::test)] async fn test_wasm_end_to_end_crowd_funding(config: impl LineraNetConfig) { use crowd_funding::{CrowdFundingAbi, InitializationArgument}; - use fungible::{FungibleTokenAbi, InitialState}; + use fungible::{FungibleTokenAbi, InitialState, Parameters}; let _guard = INTEGRATION_TEST_GUARD.lock().await; @@ -1034,9 +1048,9 @@ async fn test_wasm_end_to_end_crowd_funding(config: impl LineraNetConfig) { // Setting up the application fungible let (contract_fungible, service_fungible) = client1.build_example("fungible").await.unwrap(); - let params = fungible::Parameters::new("FUN"); + let params = Parameters::new("FUN"); let application_id_fungible = client1 - .publish_and_create::( + .publish_and_create::( contract_fungible, service_fungible, ¶ms, @@ -1057,7 +1071,7 @@ async fn test_wasm_end_to_end_crowd_funding(config: impl LineraNetConfig) { }; let (contract_crowd, service_crowd) = client1.build_example("crowd-funding").await.unwrap(); let application_id_crowd = client1 - .publish_and_create::( + .publish_and_create::, InitializationArgument>( contract_crowd, service_crowd, // TODO(#723): This hack will disappear soon. @@ -1142,7 +1156,6 @@ async fn test_wasm_end_to_end_crowd_funding(config: impl LineraNetConfig) { // #[cfg_attr(feature = "rocksdb", test_case(LocalNetConfig::new_test(Database::RocksDb, Network::Grpc) ; "rocksdb_grpc"))] #[test_log::test(tokio::test)] async fn test_wasm_end_to_end_matching_engine(config: impl LineraNetConfig) { - use fungible::{FungibleTokenAbi, InitialState}; use matching_engine::{MatchingEngineAbi, OrderNature, Parameters, Price}; let _guard = INTEGRATION_TEST_GUARD.lock().await; @@ -1179,18 +1192,18 @@ async fn test_wasm_end_to_end_matching_engine(config: impl LineraNetConfig) { let owner_b = get_fungible_account_owner(&client_b); // The initial accounts on chain_a and chain_b let accounts0 = BTreeMap::from([(owner_a, Amount::from_tokens(10))]); - let state_fungible0 = InitialState { + let state_fungible0 = fungible::InitialState { accounts: accounts0, }; let accounts1 = BTreeMap::from([(owner_b, Amount::from_tokens(9))]); - let state_fungible1 = InitialState { + let state_fungible1 = fungible::InitialState { accounts: accounts1, }; // Setting up the application fungible on chain_a and chain_b let params0 = fungible::Parameters::new("ZERO"); let token0 = client_a - .publish_and_create::( + .publish_and_create::( contract_fungible_a, service_fungible_a, ¶ms0, @@ -1202,7 +1215,7 @@ async fn test_wasm_end_to_end_matching_engine(config: impl LineraNetConfig) { .unwrap(); let params1 = fungible::Parameters::new("ONE"); let token1 = client_b - .publish_and_create::( + .publish_and_create::( contract_fungible_b, service_fungible_b, ¶ms1, @@ -1305,11 +1318,15 @@ async fn test_wasm_end_to_end_matching_engine(config: impl LineraNetConfig) { tokens: [token0, token1], }; let bytecode_id = node_service_admin - .publish_bytecode(&chain_admin, contract_matching, service_matching) + .publish_bytecode::( + &chain_admin, + contract_matching, + service_matching, + ) .await .unwrap(); let application_id_matching = node_service_admin - .create_application::( + .create_application( &chain_admin, &bytecode_id, ¶meter, @@ -1440,7 +1457,6 @@ async fn test_wasm_end_to_end_matching_engine(config: impl LineraNetConfig) { #[test_log::test(tokio::test)] async fn test_wasm_end_to_end_amm(config: impl LineraNetConfig) { use amm::{AmmAbi, Parameters}; - use fungible::{FungibleTokenAbi, InitialState}; let _guard = INTEGRATION_TEST_GUARD.lock().await; let (mut net, client_admin) = config.instantiate().await.unwrap(); @@ -1479,7 +1495,7 @@ async fn test_wasm_end_to_end_amm(config: impl LineraNetConfig) { let mut node_service1 = client1.run_node_service(8082).await.unwrap(); // Amounts of token0 that will be owned by each user - let state_fungible0 = InitialState { + let state_fungible0 = fungible::InitialState { accounts: BTreeMap::from([ (owner0, Amount::ZERO), (owner1, Amount::from_tokens(50)), @@ -1488,7 +1504,7 @@ async fn test_wasm_end_to_end_amm(config: impl LineraNetConfig) { }; // Amounts of token1 that will be owned by each user - let state_fungible1 = InitialState { + let state_fungible1 = fungible::InitialState { accounts: BTreeMap::from([ (owner0, Amount::from_tokens(50)), (owner1, Amount::ZERO), @@ -1499,13 +1515,13 @@ async fn test_wasm_end_to_end_amm(config: impl LineraNetConfig) { // Create fungible applications on the Admin chain, which will hold // the token0 and token1 amounts let fungible_bytecode_id = node_service_admin - .publish_bytecode(&chain_admin, contract_fungible, service_fungible) + .publish_bytecode::(&chain_admin, contract_fungible, service_fungible) .await .unwrap(); let params0 = fungible::Parameters::new("ZERO"); let token0 = node_service_admin - .create_application::( + .create_application( &chain_admin, &fungible_bytecode_id, ¶ms0, @@ -1516,7 +1532,7 @@ async fn test_wasm_end_to_end_amm(config: impl LineraNetConfig) { .unwrap(); let params1 = fungible::Parameters::new("ONE"); let token1 = node_service_admin - .create_application::( + .create_application( &chain_admin, &fungible_bytecode_id, ¶ms1, @@ -1562,11 +1578,11 @@ async fn test_wasm_end_to_end_amm(config: impl LineraNetConfig) { // Create AMM application on Admin chain let bytecode_id = node_service_admin - .publish_bytecode(&chain_admin, contract_amm, service_amm) + .publish_bytecode::(&chain_admin, contract_amm, service_amm) .await .unwrap(); let application_id_amm = node_service_admin - .create_application::( + .create_application( &chain_admin, &bytecode_id, ¶meters, @@ -1902,8 +1918,6 @@ async fn test_end_to_end_reconfiguration(config: LocalNetConfig) { #[cfg_attr(feature = "remote_net", test_case(RemoteNetTestingConfig::new(None) ; "remote_net_grpc"))] #[test_log::test(tokio::test)] async fn test_open_chain_node_service(config: impl LineraNetConfig) { - use fungible::{FungibleTokenAbi, InitialState}; - let _guard = INTEGRATION_TEST_GUARD.lock().await; let (mut net, client) = config.instantiate().await.unwrap(); @@ -1921,11 +1935,18 @@ async fn test_open_chain_node_service(config: impl LineraNetConfig) { // Create a fungible token application with 10 tokens for owner 1. let owner = get_fungible_account_owner(&client); let accounts = BTreeMap::from([(owner, Amount::from_tokens(10))]); - let state = InitialState { accounts }; + let state = fungible::InitialState { accounts }; let (contract, service) = client.build_example("fungible").await.unwrap(); let params = fungible::Parameters::new("FUN"); let application_id = client - .publish_and_create::(contract, service, ¶ms, &state, &[], None) + .publish_and_create::( + contract, + service, + ¶ms, + &state, + &[], + None, + ) .await .unwrap(); @@ -2600,7 +2621,7 @@ async fn test_end_to_end_retry_pending_block(config: LocalNetConfig) { #[cfg_attr(feature = "aws", test_case(LocalNetConfig::new_test(Database::DynamoDb, Network::Tcp) ; "aws_tcp"))] #[test_log::test(tokio::test)] async fn test_end_to_end_benchmark(mut config: LocalNetConfig) { - use fungible::{FungibleTokenAbi, InitialState}; + use fungible::{FungibleTokenAbi, InitialState, Parameters}; config.num_other_initial_chains = 2; let _guard = INTEGRATION_TEST_GUARD.lock().await; @@ -2617,9 +2638,16 @@ async fn test_end_to_end_benchmark(mut config: LocalNetConfig) { let accounts = BTreeMap::from([(account_owner, Amount::from_tokens(1_000_000))]); let state = InitialState { accounts }; let (contract, service) = client.build_example("fungible").await.unwrap(); - let params = fungible::Parameters::new("FUN"); + let params = Parameters::new("FUN"); let application_id = client - .publish_and_create::(contract, service, ¶ms, &state, &[], None) + .publish_and_create::( + contract, + service, + ¶ms, + &state, + &[], + None, + ) .await .unwrap(); client