jam_pvm_common/
service.rs

1use jam_types::{
2	AccumulateItem, CodeHash, Hash, RefineContext, ServiceId, Slot, TransferRecord, Vec,
3	WorkOutput, WorkPackageHash, WorkPayload,
4};
5
6/// Declare that this crate is a JAM service characterized by `$service_impl` and create necessary
7/// entry points.
8///
9/// - `$service_impl` must implement the [Service] trait.
10#[macro_export]
11macro_rules! declare_service {
12	($service_impl: ty) => {
13		#[polkavm_derive::polkavm_export]
14		extern "C" fn refine_ext(ptr: u32, size: u32) -> (u64, u64) {
15			let $crate::jam_types::RefineParams {
16				id,
17				payload,
18				package_hash,
19				context,
20				auth_code_hash,
21			} = $crate::mem::decode_buf(ptr, size);
22			let result = <$service_impl as $crate::Service>::refine(
23				id,
24				payload,
25				package_hash,
26				context,
27				auth_code_hash,
28			);
29			((&result).as_ptr() as u64, result.len() as u64)
30		}
31		#[polkavm_derive::polkavm_export]
32		extern "C" fn accumulate_ext(ptr: u32, size: u32) -> (u64, u64) {
33			let $crate::jam_types::AccumulateParams { slot, id, results } =
34				$crate::mem::decode_buf(ptr, size);
35			let maybe_hash = <$service_impl as $crate::Service>::accumulate(slot, id, results);
36			if let Some(hash) = maybe_hash {
37				((&hash).as_ptr() as u64, 32u64)
38			} else {
39				(0, 0)
40			}
41		}
42		#[polkavm_derive::polkavm_export]
43		extern "C" fn on_transfer_ext(ptr: u32, size: u32) -> (u64, u64) {
44			let $crate::jam_types::OnTransferParams { slot, id, transfers } =
45				$crate::mem::decode_buf(ptr, size);
46			<$service_impl as $crate::Service>::on_transfer(slot, id, transfers);
47			(0, 0)
48		}
49	};
50}
51
52/// The invocation trait for a JAM service.
53///
54/// The [declare_service] macro requires that its parameter implement this trait.
55pub trait Service {
56	/// The Refine entry-point, used in-core on a single Work Item.
57	///
58	/// - `id`: The index of the service being refined.
59	/// - `payload`: The payload data to process.
60	/// - `package_hash`: The hash of the Work Package.
61	/// - `context`: Various pieces of contextual information for the Refinement process.
62	/// - `auth_code_hash`: The hash of the authorizer code which was used to authorize the Work
63	///   Package.
64	///
65	/// Returns the Work Output, which will be passed into [Self::accumulate] in the on-chain
66	/// (stateful) context.
67	fn refine(
68		id: ServiceId,
69		payload: WorkPayload,
70		package_hash: WorkPackageHash,
71		context: RefineContext,
72		auth_code_hash: CodeHash,
73	) -> WorkOutput;
74
75	/// The Accumulate entry-point, used on-chain on one or more Work Item Outputs, or possibly none
76	/// in the case of an always-accumulate service.
77	///
78	/// - `slot`: The current time slot.
79	/// - `id`: The service ID being accumulated.
80	/// - `results`: The Work Outputs of the Work Items, together with additional information on the
81	///   Work Packages which brought them about.
82	fn accumulate(slot: Slot, id: ServiceId, results: Vec<AccumulateItem>) -> Option<Hash>;
83
84	/// The On Transfer entry-point, used on-chain on one or more Transfers.
85	///
86	/// - `slot`: The current time slot.
87	/// - `id`: The service ID being accumulated.
88	/// - `transfers`: Information on the Transfers to the service ID in question.
89	fn on_transfer(slot: Slot, id: ServiceId, transfers: Vec<TransferRecord>);
90}