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//! ```rust
11//! extern crate alloc;
12//! use alloc::vec::Vec;
13//! use jam_pvm_common::{declare_service, Service, accumulate::set_storage};
14//! use jam_types::*;
15//!
16//! struct MyService;
17//! declare_service!(MyService);
18//!
19//! impl Service for MyService {
20//! fn refine(
21//! _id: ServiceId,
22//! payload: WorkPayload,
23//! _package_hash: WorkPackageHash,
24//! _context: RefineContext,
25//! _auth_code_hash: CodeHash,
26//! ) -> WorkOutput {
27//! [&b"Hello "[..], payload.take().as_slice()].concat().into()
28//! }
29//! fn accumulate(_slot: Slot, _id: ServiceId, items: Vec<AccumulateItem>) -> Option<Hash> {
30//! for item in items.into_iter() {
31//! if let Ok(data) = item.result {
32//! set_storage(item.package.as_slice(), &data).expect("not enough balance?!");
33//! }
34//! }
35//! None
36//! }
37//! fn on_transfer(_slot: Slot, _id: ServiceId, _items: Vec<TransferRecord>) {}
38//! }
39//! ```
40//!
41//! ## Host-calls
42//! The host-calls available to a service or authorizer are split into four modules:
43//! - [is_authorized] for authorizers, to be called from the [Authorizer::is_authorized] function.
44//! - [refine] for services, to be called from the [Service::refine] function.
45//! - [accumulate] for services, to be called from the [Service::accumulate] function.
46//! - [on_transfer] for services, to be called from the [Service::on_transfer] function.
47//!
48//! Each module contains a set of functions that can be called from the respective entry-point
49//! function. These functions are used to interact with the PVM and the blockchain state.
50//!
51//! ## Logging
52//! Five logging macros are provided similar to those of the `log` crate, [debug], [info], [warn],
53//! [error], and [trace]. These macros are used with the non-standard PolkaJam `log` host-call and
54//! the `format` macro. The host environment is responsible for forwarding these logs to the
55//! appropriate destination.
56//!
57//! ## Features
58//! - `authorizer`: Enables the authorizer API.
59//! - `service`: Enables the service API.
60//! - `logging`: Enables the logging service; without the logging macros will evaluate any operands
61//! but otherwise have no effect.
62#![no_std]
63#![allow(clippy::unwrap_used)]
64
65extern crate alloc;
66
67#[doc(hidden)]
68pub use jam_types;
69
70#[cfg(any(feature = "authorizer", doc))]
71mod authorizer;
72#[cfg(any(feature = "authorizer", doc))]
73pub use authorizer::Authorizer;
74
75#[cfg(any(feature = "service", doc))]
76mod service;
77#[cfg(any(feature = "service", doc))]
78pub use service::Service;
79
80#[allow(dead_code)]
81mod host_calls;
82
83/// Host-call APIs available for the [Authorizer::is_authorized] entry-point.
84#[cfg(any(feature = "authorizer", doc))]
85pub mod is_authorized {
86 pub use super::host_calls::gas;
87}
88
89/// Host-call APIs available for the [Service::refine] entry-point.
90#[cfg(any(feature = "service", doc))]
91pub mod refine {
92 pub use super::host_calls::{
93 export, export_slice, expunge, foreign_historical_lookup as foreign_lookup,
94 foreign_historical_lookup_into as foreign_lookup_into, gas, historical_lookup as lookup,
95 historical_lookup_into as lookup_into, import, invoke,
96 is_foreign_historical_available as is_foreign_available,
97 is_historical_available as is_available, machine, peek, peek_into, peek_value, poke,
98 poke_value, void, zero, Fetch,
99 };
100}
101
102/// Host-call APIs available for the [Service::accumulate] entry-point.
103#[cfg(any(feature = "service", doc))]
104pub mod accumulate {
105 pub use super::host_calls::{
106 assign, bless, checkpoint, create_service, designate, eject, foreign_lookup,
107 foreign_lookup_into, forget, gas, get, get_foreign, get_foreign_storage, get_storage,
108 is_available, is_foreign_available, lookup, lookup_into, my_info, query, remove,
109 remove_storage, service_info, set, set_storage, solicit, transfer, upgrade, yield_hash,
110 zombify, ForgetImplication, LookupRequestStatus,
111 };
112}
113
114/// Host-call APIs available for the [Service::on_transfer] entry-point.
115#[cfg(any(feature = "service", doc))]
116pub mod on_transfer {
117 pub use super::host_calls::{
118 foreign_lookup, foreign_lookup_into, forget, gas, get, get_foreign, get_foreign_storage,
119 get_storage, is_available, is_foreign_available, lookup, lookup_into, my_info, remove,
120 remove_storage, service_info, set, set_storage, solicit,
121 };
122}
123
124pub(crate) mod imports;
125
126#[doc(hidden)]
127pub mod logging;
128
129#[doc(hidden)]
130pub mod mem;
131
132mod result;
133pub use result::{ApiError, ApiResult, InvokeOutcome, InvokeResult};