jam_pvm_common/lib.rs
1//! The main JAM PVM API for creating authorizers and services on JAM. This includes a trait-based
2//! invocation entry-point API as well as host-calls functions and types for working with them.
3//!
4//! In order to create a PVM executable containing a JAM service or authorizer, you must implement
5//! the [Service] or [Authorizer] in some type and then pass your type into the `declare_service!`
6//! or `declare_authorizer!` macro, respectively. This will generate the necessary entry-points for
7//! the PVM to call into your implementation.
8//!
9//! ## Example Service
10#![cfg_attr(feature = "service", doc = "```rust")]
11#![cfg_attr(not(feature = "service"), doc = "```ignore")]
12//! extern crate alloc;
13//! use alloc::vec::Vec;
14//! use jam_pvm_common::{declare_service, Service, accumulate::{set_storage, accumulate_items}};
15//! use jam_types::*;
16//!
17//! struct MyService;
18//! declare_service!(MyService);
19//!
20//! impl Service for MyService {
21//! fn refine(
22//! _core_index: CoreIndex,
23//! _item_index: usize,
24//! _service_id: ServiceId,
25//! payload: WorkPayload,
26//! _package_hash: WorkPackageHash,
27//! ) -> WorkOutput {
28//! [&b"Hello "[..], payload.take().as_slice()].concat().into()
29//! }
30//! fn accumulate(_slot: Slot, _service_id: ServiceId, _item_count: usize) -> Option<Hash> {
31//! for item in accumulate_items().into_iter() {
32//! match item {
33//! AccumulateItem::WorkItem(w) => {
34//! if let Ok(data) = w.result {
35//! set_storage(w.package.as_slice(), &data).expect("not enough balance?!");
36//! }
37//! },
38//! AccumulateItem::Transfer(t) => {
39//! // ...
40//! }
41//! }
42//! }
43//! None
44//! }
45//! }
46//! ```
47//!
48//! ## Host-calls
49//! The host-calls available to a service or authorizer are split into three modules:
50//! - [is_authorized] for authorizers, to be called from the [Authorizer::is_authorized] function.
51//! - [refine] for services, to be called from the [Service::refine] function.
52//! - [accumulate] for services, to be called from the [Service::accumulate] function.
53//!
54//! Each module contains a set of functions that can be called from the respective entry-point
55//! function. These functions are used to interact with the PVM and the blockchain state.
56//!
57//! ## Logging
58//! Five logging macros are provided similar to those of the `log` crate, [debug], [info], [warn],
59//! [error], and [trace]. These macros are used with the non-standard PolkaJam `log` host-call and
60//! the `format` macro. The host environment is responsible for forwarding these logs to the
61//! appropriate destination.
62//!
63//! ## Features
64//! - `authorizer`: Enables the authorizer API.
65//! - `service`: Enables the service API.
66//! - `logging`: Enables the logging service; without the logging macros will evaluate any operands
67//! but otherwise have no effect.
68#![no_std]
69#![allow(clippy::unwrap_used)]
70#![allow(unexpected_cfgs)] // To prevent warnings about `target_env = "polkavm"`.
71
72extern crate alloc;
73
74#[doc(hidden)]
75pub use jam_types;
76
77#[cfg(any(feature = "authorizer", doc))]
78mod authorizer;
79#[cfg(any(feature = "authorizer", doc))]
80pub use authorizer::Authorizer;
81
82#[cfg(any(feature = "service", doc))]
83mod service;
84#[cfg(any(feature = "service", doc))]
85pub use service::Service;
86
87#[allow(dead_code)]
88mod host_calls;
89
90#[cfg(target_env = "polkavm")]
91mod panic_handler;
92#[cfg(any(feature = "service", feature = "authorizer", doc))]
93pub mod startup;
94
95/// Host-call APIs available for the [Authorizer::is_authorized] entry-point.
96#[cfg(any(feature = "authorizer", doc))]
97pub mod is_authorized {
98 pub use super::host_calls::{
99 fetch_wrappers::{
100 auth_token, authorizer, protocol_parameters, refine_context, work_item_payload,
101 work_item_summary, work_items_summary, work_package,
102 },
103 gas,
104 };
105}
106
107/// Host-call APIs available for the [Service::refine] entry-point.
108#[cfg(any(feature = "service", doc))]
109pub mod refine {
110 pub use super::host_calls::{
111 export, export_slice, expunge,
112 fetch_wrappers::{
113 any_extrinsic, any_import, auth_token, auth_trace, authorizer, entropy, extrinsic,
114 extrinsic_slice, import, protocol_parameters, refine_context, work_item_payload,
115 work_item_summary, work_items_summary, work_package,
116 },
117 foreign_historical_lookup as foreign_lookup,
118 foreign_historical_lookup_into as foreign_lookup_into, gas, historical_lookup as lookup,
119 historical_lookup_into as lookup_into, invoke,
120 is_foreign_historical_available as is_foreign_available,
121 is_historical_available as is_available, machine, peek, peek_into, peek_value, poke,
122 poke_value, void, zero,
123 };
124}
125
126/// Host-call APIs available for the [Service::accumulate] entry-point.
127#[cfg(any(feature = "service", doc))]
128pub mod accumulate {
129 pub use super::host_calls::{
130 assign, bless, checkpoint, create_service, create_service_ext, designate, eject,
131 fetch_wrappers::{accumulate_item, accumulate_items, entropy, protocol_parameters},
132 foreign_lookup, foreign_lookup_into, forget, gas, get, get_foreign, get_foreign_storage,
133 get_storage, is_available, is_foreign_available, lookup, lookup_into, my_info, provide,
134 query, remove, remove_storage, service_info, set, set_storage, solicit, transfer, upgrade,
135 yield_hash, zombify, ForgetImplication, LookupRequestStatus,
136 };
137}
138
139#[cfg(feature = "service")]
140#[doc(hidden)]
141pub mod internal {
142 pub use super::host_calls::raw_service_info_field;
143}
144
145#[doc(hidden)]
146pub mod imports;
147
148#[doc(hidden)]
149pub mod logging;
150
151#[doc(hidden)]
152pub mod mem;
153
154mod result;
155pub use result::{ApiError, ApiResult, InvokeOutcome, InvokeResult};