linera_sdk/lib.rs
1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! This module provides an SDK for developing Linera applications using Rust.
5//!
6//! A Linera application consists of two WebAssembly binaries: a contract and a service.
7//! Both binaries have access to the same application and chain specific storage. The service only
8//! has read-only access, while the contract can write to it. The storage should be used to store
9//! the application state, which is persisted across blocks. The state can be a custom type that
10//! uses [`linera-views`](https://docs.rs/linera-views/latest/linera_views/index.html), a framework
11//! that allows lazily loading selected parts of the state. This is useful if the application's
12//! state is large and doesn't need to be loaded in its entirety for every execution.
13//!
14//! The contract binary should create a type to implement the [`Contract`](crate::Contract) trait.
15//! The type can store the [`ContractRuntime`](contract::ContractRuntime) and the state, and must
16//! have its implementation exported by using the [`contract!`](crate::contract!) macro.
17//!
18//! The service binary should create a type to implement the [`Service`](crate::Service) trait.
19//! The type can store the [`ServiceRuntime`](service::ServiceRuntime) and the state, and must have
20//! its implementation exported by using the [`service!`](crate::service!) macro.
21//!
22//! # Examples
23//!
24//! The [`examples`](https://github.com/linera-io/linera-protocol/tree/main/examples)
25//! directory contains some example applications.
26
27#[macro_use]
28pub mod util;
29
30pub mod abis;
31mod base;
32pub mod contract;
33#[cfg(feature = "ethereum")]
34pub mod ethereum;
35mod extensions;
36pub mod graphql;
37pub mod linera_base_types;
38mod log;
39pub mod service;
40#[cfg(with_testing)]
41pub mod test;
42pub mod views;
43
44use std::fmt::Debug;
45
46pub use bcs;
47pub use linera_base::{
48 abi,
49 data_types::{Resources, SendMessageRequest},
50 ensure, http,
51};
52use linera_base::{
53 abi::{ContractAbi, ServiceAbi, WithContractAbi, WithServiceAbi},
54 data_types::StreamUpdate,
55};
56use serde::{de::DeserializeOwned, Serialize};
57pub use serde_json;
58
59#[doc(hidden)]
60pub use self::{contract::export_contract, service::export_service};
61pub use self::{
62 contract::ContractRuntime,
63 extensions::{FromBcsBytes, ToBcsBytes},
64 log::{ContractLogger, ServiceLogger},
65 service::ServiceRuntime,
66 views::{KeyValueStore, ViewStorageContext},
67};
68
69/// The contract interface of a Linera application.
70///
71/// As opposed to the [`Service`] interface of an application, contract entry points
72/// are triggered by the execution of blocks in a chain. Their execution may modify
73/// storage and is gas-metered.
74///
75/// Below we use the word "transaction" to refer to the current operation or message being
76/// executed.
77#[allow(async_fn_in_trait)]
78pub trait Contract: WithContractAbi + ContractAbi + Sized {
79 /// The type of message executed by the application.
80 ///
81 /// Messages are executed when a message created by the same application is received
82 /// from another chain and accepted in a block.
83 type Message: Serialize + DeserializeOwned + Debug;
84
85 /// Immutable parameters specific to this application (e.g. the name of a token).
86 type Parameters: Serialize + DeserializeOwned + Clone + Debug;
87
88 /// Instantiation argument passed to a new application on the chain that created it
89 /// (e.g. an initial amount of tokens minted).
90 ///
91 /// To share configuration data on every chain, use [`Contract::Parameters`]
92 /// instead.
93 type InstantiationArgument: Serialize + DeserializeOwned + Debug;
94
95 /// Event values for streams created by this application.
96 type EventValue: Serialize + DeserializeOwned + Debug;
97
98 /// Creates an in-memory instance of the contract handler.
99 async fn load(runtime: ContractRuntime<Self>) -> Self;
100
101 /// Instantiates the application on the chain that created it.
102 ///
103 /// This is only called once when the application is created and only on the microchain that
104 /// created the application.
105 async fn instantiate(&mut self, argument: Self::InstantiationArgument);
106
107 /// Applies an operation from the current block.
108 ///
109 /// Operations are created by users and added to blocks, serving as the starting point for an
110 /// application's execution.
111 async fn execute_operation(&mut self, operation: Self::Operation) -> Self::Response;
112
113 /// Applies a message originating from a cross-chain message.
114 ///
115 /// Messages are sent across chains. These messages are created and received by
116 /// the same application. Messages can be either single-sender and single-receiver, or
117 /// single-sender and multiple-receivers. The former allows sending cross-chain messages to the
118 /// application on some other specific chain, while the latter uses broadcast channels to
119 /// send a message to multiple other chains where the application is subscribed to a
120 /// sender channel on this chain.
121 ///
122 /// For a message to be executed, a user must mark it to be received in a block of the receiver
123 /// chain.
124 async fn execute_message(&mut self, message: Self::Message);
125
126 /// Reacts to new events on streams.
127 ///
128 /// This is called whenever there is a new event on any stream that this application
129 /// subscribes to.
130 async fn process_streams(&mut self, _updates: Vec<StreamUpdate>) {}
131
132 /// Finishes the execution of the current transaction.
133 ///
134 /// This is called once at the end of the transaction, to allow all applications that
135 /// participated in the transaction to perform any final operations, such as persisting their
136 /// state.
137 ///
138 /// The application may also cancel the transaction by panicking if there are any pendencies.
139 async fn store(self);
140}
141
142/// The service interface of a Linera application.
143///
144/// As opposed to the [`Contract`] interface of an application, service entry points
145/// are triggered by JSON queries (typically GraphQL). Their execution cannot modify
146/// storage and is not gas-metered.
147#[allow(async_fn_in_trait)]
148pub trait Service: WithServiceAbi + ServiceAbi + Sized {
149 /// Immutable parameters specific to this application.
150 type Parameters: Serialize + DeserializeOwned + Send + Sync + Clone + Debug + 'static;
151
152 /// Creates an in-memory instance of the service handler.
153 async fn new(runtime: ServiceRuntime<Self>) -> Self;
154
155 /// Executes a read-only query on the state of this application.
156 async fn handle_query(&self, query: Self::Query) -> Self::QueryResponse;
157}