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}