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#![deny(missing_docs)]
28
29#[macro_use]
30pub mod util;
31
32pub mod abis;
33mod base;
34pub mod contract;
35#[cfg(feature = "ethereum")]
36pub mod ethereum;
37mod extensions;
38pub mod graphql;
39pub mod linera_base_types;
40mod log;
41pub mod service;
42#[cfg(with_testing)]
43pub mod test;
44pub mod views;
45
46use std::fmt::Debug;
47
48pub use bcs;
49pub use linera_base::{
50 abi,
51 data_types::{Resources, SendMessageRequest},
52 ensure, http,
53};
54use linera_base::{
55 abi::{ContractAbi, ServiceAbi, WithContractAbi, WithServiceAbi},
56 crypto::CryptoHash,
57 data_types::StreamUpdate,
58 doc_scalar,
59};
60use serde::{de::DeserializeOwned, Deserialize, Serialize};
61pub use serde_json;
62
63#[doc(hidden)]
64pub use self::{contract::export_contract, service::export_service};
65pub use self::{
66 contract::ContractRuntime,
67 extensions::{FromBcsBytes, ToBcsBytes},
68 log::{ContractLogger, ServiceLogger},
69 service::ServiceRuntime,
70 views::{KeyValueStore, ViewStorageContext},
71};
72
73/// Hash of a data blob.
74#[derive(Eq, Hash, PartialEq, Debug, Serialize, Deserialize, Clone, Copy)]
75pub struct DataBlobHash(pub CryptoHash);
76
77doc_scalar!(DataBlobHash, "Hash of a Data Blob");
78
79/// The contract interface of a Linera application.
80///
81/// As opposed to the [`Service`] interface of an application, contract entry points
82/// are triggered by the execution of blocks in a chain. Their execution may modify
83/// storage and is gas-metered.
84///
85/// Below we use the word "transaction" to refer to the current operation or message being
86/// executed.
87#[allow(async_fn_in_trait)]
88pub trait Contract: WithContractAbi + ContractAbi + Sized {
89 /// The type of message executed by the application.
90 ///
91 /// Messages are executed when a message created by the same application is received
92 /// from another chain and accepted in a block.
93 type Message: Serialize + DeserializeOwned + Debug;
94
95 /// Immutable parameters specific to this application (e.g. the name of a token).
96 type Parameters: Serialize + DeserializeOwned + Clone + Debug;
97
98 /// Instantiation argument passed to a new application on the chain that created it
99 /// (e.g. an initial amount of tokens minted).
100 ///
101 /// To share configuration data on every chain, use [`Contract::Parameters`]
102 /// instead.
103 type InstantiationArgument: Serialize + DeserializeOwned + Debug;
104
105 /// Event values for streams created by this application.
106 type EventValue: Serialize + DeserializeOwned + Debug;
107
108 /// Creates an in-memory instance of the contract handler.
109 async fn load(runtime: ContractRuntime<Self>) -> Self;
110
111 /// Instantiates the application on the chain that created it.
112 ///
113 /// This is only called once when the application is created and only on the microchain that
114 /// created the application.
115 async fn instantiate(&mut self, argument: Self::InstantiationArgument);
116
117 /// Applies an operation from the current block.
118 ///
119 /// Operations are created by users and added to blocks, serving as the starting point for an
120 /// application's execution.
121 async fn execute_operation(&mut self, operation: Self::Operation) -> Self::Response;
122
123 /// Applies a message originating from a cross-chain message.
124 ///
125 /// Messages are sent across chains. These messages are created and received by
126 /// the same application. Messages can be either single-sender and single-receiver, or
127 /// single-sender and multiple-receivers. The former allows sending cross-chain messages to the
128 /// application on some other specific chain, while the latter uses broadcast channels to
129 /// send a message to multiple other chains where the application is subscribed to a
130 /// sender channel on this chain.
131 ///
132 /// For a message to be executed, a user must mark it to be received in a block of the receiver
133 /// chain.
134 async fn execute_message(&mut self, message: Self::Message);
135
136 /// Reacts to new events on streams.
137 ///
138 /// This is called whenever there is a new event on any stream that this application
139 /// subscribes to.
140 async fn process_streams(&mut self, _updates: Vec<StreamUpdate>) {}
141
142 /// Finishes the execution of the current transaction.
143 ///
144 /// This is called once at the end of the transaction, to allow all applications that
145 /// participated in the transaction to perform any final operations, such as persisting their
146 /// state.
147 ///
148 /// The application may also cancel the transaction by panicking if there are any pendencies.
149 async fn store(self);
150}
151
152/// The service interface of a Linera application.
153///
154/// As opposed to the [`Contract`] interface of an application, service entry points
155/// are triggered by JSON queries (typically GraphQL). Their execution cannot modify
156/// storage and is not gas-metered.
157#[allow(async_fn_in_trait)]
158pub trait Service: WithServiceAbi + ServiceAbi + Sized {
159 /// Immutable parameters specific to this application.
160 type Parameters: Serialize + DeserializeOwned + Send + Sync + Clone + Debug + 'static;
161
162 /// Creates an in-memory instance of the service handler.
163 async fn new(runtime: ServiceRuntime<Self>) -> Self;
164
165 /// Executes a read-only query on the state of this application.
166 async fn handle_query(&self, query: Self::Query) -> Self::QueryResponse;
167}