openvm_deferral_guest/lib.rs
1#![no_std]
2
3use strum_macros::FromRepr;
4
5mod ops;
6pub use ops::*;
7
8/// This is custom-1 defined in RISC-V spec document
9pub const OPCODE: u8 = 0x2b;
10/// All deferral operations use funct3 0b111
11pub const DEFERRAL_FUNCT3: u8 = 0b111;
12/// Low bits in immediate used to pick deferral sub-opcode
13pub const DEFERRAL_OPCODE_BITS: u32 = 2;
14
15/// Maximum number of deferral circuits, as constrained in the deferrals part of the
16/// continuations framework. Note that each deferral instruction stores its deferral
17/// idx in the most significant 10 bits of the immediate field.
18pub const MAX_DEF_CIRCUITS: u16 = 512;
19
20/// Number of bytes in a commit, used as identifiers for raw deferral inputs/outputs
21pub const COMMIT_NUM_BYTES: usize = 32;
22/// Commit type use as a raw deferral input/output identifier
23pub type Commit = [u8; COMMIT_NUM_BYTES];
24
25/// Key for looking up raw output.
26///
27/// Trusted only when returned by `deferred_compute`. Manually constructed keys are
28/// not trusted deferral results: `get_deferred_output` authenticates output bytes
29/// against the key, but only `CALL` (via `deferred_compute`) establishes that the
30/// key came from a deferred computation.
31#[repr(C, align(4))]
32#[derive(Debug, Copy, Clone, PartialEq, Eq)]
33pub struct OutputKey {
34 pub output_commit: Commit,
35 pub output_len: u64,
36}
37
38impl OutputKey {
39 /// Constructs an `OutputKey` value.
40 ///
41 /// This does not make the key a trusted deferral result.
42 #[inline(always)]
43 pub const fn new(output_commit: Commit, output_len: u64) -> Self {
44 Self {
45 output_commit,
46 output_len,
47 }
48 }
49
50 #[inline(always)]
51 pub fn as_ptr(&self) -> *const u8 {
52 (self as *const OutputKey).cast::<u8>()
53 }
54
55 #[inline(always)]
56 pub fn as_mut_ptr(&mut self) -> *mut u8 {
57 (self as *mut OutputKey).cast::<u8>()
58 }
59}
60
61/// Deferral sub-opcode encoded in immediate low bits
62#[derive(Debug, Copy, Clone, PartialEq, Eq, FromRepr)]
63#[repr(u16)]
64pub enum DeferralImmOpcode {
65 Call = 0,
66 Output = 1,
67}
68
69/// Encode deferral immediate as [def_idx(10 bits) | opcode(2 bits)]
70#[inline(always)]
71pub const fn encode_deferral_imm(deferral_idx: u16, opcode: DeferralImmOpcode) -> u16 {
72 (deferral_idx << DEFERRAL_OPCODE_BITS) | (opcode as u16)
73}