jam_pvm_common/
service.rs

1use jam_types::{CoreIndex, Hash, ServiceId, Slot, WorkOutput, WorkPackageHash, WorkPayload};
2
3/// Declare that this crate is a JAM service characterized by `$service_impl` and create necessary
4/// entry points.
5///
6/// - `$service_impl` must implement the [Service] trait.
7#[macro_export]
8macro_rules! declare_service {
9	($service_impl: ty) => {
10		#[polkavm_derive::polkavm_export]
11		extern "C" fn refine_ext(ptr: u32, size: u32) -> (u64, u64) {
12			$crate::startup::load_protocol_parameters();
13			let $crate::jam_types::RefineParams {
14				core_index,
15				item_index,
16				service_id,
17				payload,
18				package_hash,
19			} = $crate::mem::decode_buf(ptr, size);
20			let result = <$service_impl as $crate::Service>::refine(
21				core_index,
22				item_index as _,
23				service_id,
24				payload,
25				package_hash,
26			);
27			let result = result.leak();
28			(result.as_ptr() as u64, result.len() as u64)
29		}
30		#[polkavm_derive::polkavm_export]
31		extern "C" fn accumulate_ext(ptr: u32, size: u32) -> (u64, u64) {
32			$crate::startup::load_protocol_parameters();
33			let $crate::jam_types::AccumulateParams { slot, service_id, item_count } =
34				$crate::mem::decode_buf(ptr, size);
35			let maybe_hash =
36				<$service_impl as $crate::Service>::accumulate(slot, service_id, item_count as _);
37			if let Some(hash) = maybe_hash {
38				let hash = ::alloc::boxed::Box::leak(::alloc::boxed::Box::new(hash));
39				(hash.as_ptr() as u64, hash.len() as u64)
40			} else {
41				(0, 0)
42			}
43		}
44	};
45}
46
47/// The invocation trait for a JAM service.
48///
49/// The [declare_service] macro requires that its parameter implement this trait.
50pub trait Service {
51	/// The Refine entry-point, used in-core on a single Work Item.
52	///
53	/// - `core_index`: The index of the core processing the work item.
54	/// - `item_index`: The index of the current work item.
55	/// - `service_id`: The index of the service being refined.
56	/// - `payload`: The payload data to process.
57	/// - `package_hash`: The hash of the Work Package.
58	///
59	/// Returns the Work Output, which will be passed into [Self::accumulate] in the on-chain
60	/// (stateful) context.
61	fn refine(
62		core_index: CoreIndex,
63		item_index: usize,
64		service_id: ServiceId,
65		payload: WorkPayload,
66		package_hash: WorkPackageHash,
67	) -> WorkOutput;
68
69	/// The Accumulate entry-point, used on-chain on one or more Work Item Outputs or Transfers,
70	/// or possibly none in the case of an always-accumulate service.
71	///
72	/// - `slot`: The current time slot.
73	/// - `service_id`: The service ID being accumulated.
74	/// - `item_count`: The number of items to accumulate. May be Work Outputs or Transfers.
75	fn accumulate(slot: Slot, service_id: ServiceId, item_count: usize) -> Option<Hash>;
76}