Skip to content

Commit

Permalink
[feat] Implement sys_rand (#1294)
Browse files Browse the repository at this point in the history
* Implement `sys_rand`, add the corresponding integration test

* Fix lint error

* Make this new file an example

* Reorder enums

* Fix `len` usage

* Fix `len` again and move the test to rv32im tests

* Remove native test

* Remove redundant `eprintln`
  • Loading branch information
Golovanov399 authored Jan 26, 2025
1 parent 53b27eb commit 0a77e95
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 136 deletions.
8 changes: 4 additions & 4 deletions crates/toolchain/openvm/src/pal_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/// operations in the same way: there is no operating system and even the standard library should be
/// directly handled with intrinsics.
use openvm_platform::{fileno::*, memory::sys_alloc_aligned, rust_rt::terminate, WORD_SIZE};
use openvm_rv32im_guest::raw_print_str_from_bytes;
use openvm_rv32im_guest::{hint_buffer_u32, hint_random, raw_print_str_from_bytes};

const DIGEST_WORDS: usize = 8;

Expand Down Expand Up @@ -71,9 +71,9 @@ pub unsafe extern "C" fn sys_sha_buffer(
///
/// `recv_buf` must be aligned and dereferenceable.
#[no_mangle]
pub unsafe extern "C" fn sys_rand(_recv_buf: *mut u32, _words: usize) {
crate::io::println("sys_rand is unimplemented");
terminate::<{ exit_code::UNIMP }>();
pub unsafe extern "C" fn sys_rand(recv_buf: *mut u32, words: usize) {
hint_random(words);
hint_buffer_u32!(recv_buf, words);
}

/// # Safety
Expand Down
132 changes: 0 additions & 132 deletions extensions/native/tests/programs/compiler_output.txt

This file was deleted.

32 changes: 32 additions & 0 deletions extensions/rv32im/circuit/src/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ impl<F: PrimeField32> VmExtension<F> for Rv32I {
phantom::Rv32HintInputSubEx,
PhantomDiscriminant(Rv32Phantom::HintInput as u16),
)?;
builder.add_phantom_sub_executor(
phantom::Rv32HintRandomSubEx::new(),
PhantomDiscriminant(Rv32Phantom::HintRandom as u16),
)?;
builder.add_phantom_sub_executor(
phantom::Rv32PrintStrSubEx,
PhantomDiscriminant(Rv32Phantom::PrintStr as u16),
Expand Down Expand Up @@ -471,10 +475,19 @@ mod phantom {
};
use openvm_instructions::PhantomDiscriminant;
use openvm_stark_backend::p3_field::{Field, PrimeField32};
use rand::{rngs::OsRng, Rng};

use crate::adapters::unsafe_read_rv32_register;

pub struct Rv32HintInputSubEx;
pub struct Rv32HintRandomSubEx {
rng: OsRng,
}
impl Rv32HintRandomSubEx {
pub fn new() -> Self {
Self { rng: OsRng }
}
}
pub struct Rv32PrintStrSubEx;

impl<F: Field> PhantomSubExecutor<F> for Rv32HintInputSubEx {
Expand Down Expand Up @@ -508,6 +521,25 @@ mod phantom {
}
}

impl<F: PrimeField32> PhantomSubExecutor<F> for Rv32HintRandomSubEx {
fn phantom_execute(
&mut self,
memory: &MemoryController<F>,
streams: &mut Streams<F>,
_: PhantomDiscriminant,
a: F,
_: F,
_: u16,
) -> eyre::Result<()> {
let len = unsafe_read_rv32_register(memory, a) as usize;
streams.hint_stream.clear();
streams.hint_stream.extend(
std::iter::repeat_with(|| F::from_canonical_u8(self.rng.gen::<u8>())).take(len * 4),
);
Ok(())
}
}

impl<F: PrimeField32> PhantomSubExecutor<F> for Rv32PrintStrSubEx {
fn phantom_execute(
&mut self,
Expand Down
12 changes: 12 additions & 0 deletions extensions/rv32im/guest/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ pub fn hint_input() {
);
}

/// Reset the hint stream with `len` random `u32`s
#[inline(always)]
pub fn hint_random(len: usize) {
openvm_platform::custom_insn_i!(
opcode = SYSTEM_OPCODE,
funct3 = PHANTOM_FUNCT3,
rd = In len,
rs1 = Const "x0",
imm = Const PhantomImm::HintRandom as u16
);
}

/// Store rs1 to [[rd] + imm]_2.
#[macro_export]
macro_rules! reveal {
Expand Down
1 change: 1 addition & 0 deletions extensions/rv32im/guest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ pub const CSRRW_FUNCT3: u8 = 0b001;
pub enum PhantomImm {
HintInput = 0,
PrintStr,
HintRandom,
}
18 changes: 18 additions & 0 deletions extensions/rv32im/tests/programs/examples/hashmap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![cfg_attr(not(feature = "std"), no_main)]
#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;

use std::collections::HashMap;

openvm::entry!(main);

fn main() {
let mut map = HashMap::new();
map.insert(1, 2);
map.insert(2, 8);
assert!(map.get(&1) == Some(&2));
assert!(map.get(&2) == Some(&8));
assert!(!map.contains_key(&3));
println!("{:?}", map.get(&1).unwrap());
}
16 changes: 16 additions & 0 deletions extensions/rv32im/tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,22 @@ mod tests {
Ok(())
}

#[test]
fn test_hashmap() -> Result<()> {
let elf =
build_example_program_at_path_with_features(get_programs_dir!(), "hashmap", ["std"])?;
let exe = VmExe::from_elf(
elf,
Transpiler::<F>::default()
.with_extension(Rv32ITranspilerExtension)
.with_extension(Rv32MTranspilerExtension)
.with_extension(Rv32IoTranspilerExtension),
)?;
let config = Rv32ImConfig::default();
air_test(config, exe);
Ok(())
}

#[test]
fn test_tiny_mem_test() -> Result<()> {
let elf = build_example_program_at_path_with_features(
Expand Down
2 changes: 2 additions & 0 deletions extensions/rv32im/transpiler/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,6 @@ pub enum Rv32Phantom {
HintInput = 0x20,
/// Peek string from memory and print it to stdout.
PrintStr,
/// Prepare given amount of random numbers for hinting.
HintRandom,
}
6 changes: 6 additions & 0 deletions extensions/rv32im/transpiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ impl<F: PrimeField32> TranspilerExtension<F> for Rv32ITranspilerExtension {
F::ZERO,
0,
),
PhantomImm::HintRandom => Instruction::phantom(
PhantomDiscriminant(Rv32Phantom::HintRandom as u16),
F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
F::ZERO,
0,
),
PhantomImm::PrintStr => Instruction::phantom(
PhantomDiscriminant(Rv32Phantom::PrintStr as u16),
F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
Expand Down

0 comments on commit 0a77e95

Please sign in to comment.