Skip to main content

ab_riscv_benchmarks/
host_utils.rs

1use ab_blake3::{CHUNK_LEN, OUT_LEN};
2use ab_contract_file::instruction::{ContractInstruction, ContractRegister};
3use ab_core_primitives::ed25519::{Ed25519PublicKey, Ed25519Signature};
4use ab_io_type::trivial_type::TrivialType;
5use core::mem::offset_of;
6
7/// Contract file bytes
8pub const RISCV_CONTRACT_BYTES: &[u8] = cfg_select! {
9    not(feature = "build-contract") => &[],
10    _ => {
11        include_bytes!(env!("CONTRACT_PATH"))
12    }
13};
14
15// TODO: Generate similar helper data structures in the `#[contract]` macro itself, maybe introduce
16//  `SimpleInternalArgs` data trait for this or something
17/// Helper data structure for [`Benchmarks::blake3_hash_chunk()`] method
18///
19/// [`Benchmarks::blake3_hash_chunk()`]: crate::Benchmarks::blake3_hash_chunk
20#[derive(Debug, Copy, Clone, TrivialType)]
21#[repr(C)]
22pub struct Blake3HashChunkInternalArgs {
23    chunk_ptr: u64,
24    chunk_size: u32,
25    chunk_capacity: u32,
26    result_ptr: u64,
27    chunk: [u8; CHUNK_LEN],
28    result: [u8; OUT_LEN],
29}
30
31impl Blake3HashChunkInternalArgs {
32    /// Create a new instance
33    pub fn new(internal_args_addr: u64, chunk: [u8; CHUNK_LEN]) -> Self {
34        Self {
35            chunk_ptr: internal_args_addr + offset_of!(Self, chunk) as u64,
36            chunk_size: CHUNK_LEN as u32,
37            chunk_capacity: CHUNK_LEN as u32,
38            result_ptr: internal_args_addr + offset_of!(Self, result) as u64,
39            chunk,
40            result: [0; _],
41        }
42    }
43
44    /// Extract result
45    pub fn result(&self) -> [u8; OUT_LEN] {
46        self.result
47    }
48}
49
50// TODO: Generate similar helper data structures in the `#[contract]` macro itself, maybe introduce
51//  `SimpleInternalArgs` data trait for this or something
52/// Helper data structure for [`Benchmarks::ed25519_verify()`] method
53///
54/// [`Benchmarks::ed25519_verify()`]: crate::Benchmarks::ed25519_verify
55#[derive(Debug, Copy, Clone, TrivialType)]
56#[repr(C)]
57pub struct Ed25519VerifyInternalArgs {
58    pub public_key_ptr: u64,
59    pub public_key_size: u32,
60    pub public_key_capacity: u32,
61    pub signature_ptr: u64,
62    pub signature_size: u32,
63    pub signature_capacity: u32,
64    pub message_ptr: u64,
65    pub message_size: u32,
66    pub message_capacity: u32,
67    pub result_ptr: u64,
68    pub public_key: Ed25519PublicKey,
69    pub signature: Ed25519Signature,
70    pub message: [u8; OUT_LEN],
71    pub result: bool,
72    /// Explicit trailing padding.
73    ///
74    /// The host copies the byte representation of this data structure into guest memory, which is
75    /// only sound if every byte of it is initialized, hence implicit padding must not exist here.
76    pub padding: [u8; 7],
77}
78
79impl Ed25519VerifyInternalArgs {
80    /// Create a new instance
81    pub fn new(
82        internal_args_addr: u64,
83        public_key: Ed25519PublicKey,
84        signature: Ed25519Signature,
85        message: [u8; OUT_LEN],
86    ) -> Self {
87        Self {
88            public_key_ptr: internal_args_addr + offset_of!(Self, public_key) as u64,
89            public_key_size: Ed25519PublicKey::SIZE as u32,
90            public_key_capacity: Ed25519PublicKey::SIZE as u32,
91            signature_ptr: internal_args_addr + offset_of!(Self, signature) as u64,
92            signature_size: Ed25519Signature::SIZE as u32,
93            signature_capacity: Ed25519Signature::SIZE as u32,
94            message_ptr: internal_args_addr + offset_of!(Self, message) as u64,
95            message_size: OUT_LEN as u32,
96            message_capacity: OUT_LEN as u32,
97            result_ptr: internal_args_addr + offset_of!(Self, result) as u64,
98            public_key,
99            signature,
100            message,
101            result: false,
102            padding: [0; _],
103        }
104    }
105
106    /// Extract result
107    pub fn result(&self) -> bool {
108        self.result
109    }
110}
111
112/// Instruction stored by `BasicEagerInstructions::decode()` in slots whose bytes do not decode
113/// into a valid instruction and after the last one.
114///
115/// Contract code is only expected to contain legal instructions, so this is only reachable by
116/// jumping into the middle of one or by falling through the end of the code. `unimp` always fails,
117/// so it never continues to the next instruction, as `BasicEagerInstructions::decode()`
118/// requires.
119pub const UNDECODABLE_INSTRUCTION: ContractInstruction = ContractInstruction::Unimp {
120    rs1: ContractRegister::Zero,
121    rs2: ContractRegister::Zero,
122};