mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-01-11 02:07:59 -05:00
add a runtime crate
Update riscv/runtime/src/lib.rs Co-authored-by: chriseth <chris@ethereum.org> package runtime lib to compile single files Remove need for loop{} in main Remove 'extern "C"' from main declaration implement mem* funcs in the runtime Co-Authored-by: chriseth <chris@ethereum.org> fix a couple endianness and alignment issues remove unused build entry in compiler/Cargo.toml more review feedback fix clippy linter error update README Remove all #[no_main] Add test runner for memfuncs.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,3 +8,5 @@ Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
riscv/runtime/target
|
||||
14
README.md
14
README.md
@@ -45,10 +45,10 @@ Note that this is the full and only input file you need for the whole process!
|
||||
```rust
|
||||
#![no_std]
|
||||
|
||||
use core::arch::asm;
|
||||
use runtime::get_prover_input;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> ! {
|
||||
pub fn main() {
|
||||
let mut buffer = [0u32; 100];
|
||||
let proposed_sum = get_prover_input(0);
|
||||
let len = get_prover_input(1) as usize;
|
||||
@@ -58,16 +58,6 @@ pub extern "C" fn main() -> ! {
|
||||
}
|
||||
let sum: u32 = buffer[..len].iter().sum();
|
||||
assert!(sum == proposed_sum);
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_prover_input(index: u32) -> u32 {
|
||||
let mut value: u32;
|
||||
unsafe {
|
||||
asm!("ecall", lateout("a0") value, in("a0") index);
|
||||
}
|
||||
value
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
8
riscv/runtime/Cargo.toml
Normal file
8
riscv/runtime/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "runtime"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
141
riscv/runtime/src/lib.rs
Normal file
141
riscv/runtime/src/lib.rs
Normal file
@@ -0,0 +1,141 @@
|
||||
#![no_std]
|
||||
#![feature(start)]
|
||||
|
||||
use core::arch::asm;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_panic: &PanicInfo<'_>) -> ! {
|
||||
// activate after #176 has been printed
|
||||
// print(format!("panic at line {} in file {}\n", panic.location().line(), panic.location().file()));
|
||||
unsafe {
|
||||
asm!("unimp");
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_prover_input(index: u32) -> u32 {
|
||||
let mut value: u32;
|
||||
unsafe {
|
||||
asm!("ecall", lateout("a0") value, in("a0") index);
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
fn main();
|
||||
}
|
||||
#[no_mangle]
|
||||
#[start]
|
||||
pub unsafe extern "C" fn __runtime_start() -> ! {
|
||||
unsafe {
|
||||
main();
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn __runtime_memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
|
||||
if (src as u32) % 4 == 0 && (dest as u32) % 4 == 0 {
|
||||
memcpy_aligned(dest, src, n);
|
||||
} else {
|
||||
for i in 0..n {
|
||||
*dest.offset(i as isize) = *src.offset(i as isize);
|
||||
}
|
||||
}
|
||||
dest
|
||||
}
|
||||
|
||||
pub unsafe fn memcpy_aligned(dest: *mut u8, src: *const u8, n: usize) {
|
||||
let mut i: isize = 0;
|
||||
while i + 3 < n as isize {
|
||||
*((dest.offset(i)) as *mut u32) = *((src.offset(i)) as *mut u32);
|
||||
i += 4;
|
||||
}
|
||||
if i < n as isize {
|
||||
let value = *((src.offset(i)) as *mut u32);
|
||||
let dest_value = (dest.offset(i)) as *mut u32;
|
||||
let mask = (1 << (((n as isize - i) * 8) as u32)) - 1;
|
||||
*dest_value = (*dest_value & !mask) | (value & mask);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn __runtime_memset(dest: *mut u8, val: u8, n: usize) -> *mut u8 {
|
||||
let mut i: isize = 0;
|
||||
let pattern = (val as u32) << 24 | (val as u32) << 16 | (val as u32) << 8 | (val as u32);
|
||||
|
||||
// Prologue: set bytes in the first non-aligned word
|
||||
let first_word_offset = (dest as u32) % 4;
|
||||
if first_word_offset != 0 {
|
||||
let aligned_dest = dest.offset(-(first_word_offset as isize)) as *mut u32;
|
||||
let mask = (1 << ((first_word_offset * 8) as u32)) - 1;
|
||||
*aligned_dest = (*aligned_dest & mask) | (pattern & !mask);
|
||||
i += 4 - first_word_offset as isize;
|
||||
}
|
||||
|
||||
// Set all full words
|
||||
while i + 3 < n as isize {
|
||||
*((dest.offset(i)) as *mut u32) = pattern;
|
||||
i += 4;
|
||||
}
|
||||
|
||||
// last part: set the final word
|
||||
if i < n as isize {
|
||||
let dest_value = (dest.offset(i)) as *mut u32;
|
||||
let mask = (1 << (((n as isize - i) * 8) as u32)) - 1;
|
||||
*dest_value = (*dest_value & !mask) | (pattern & mask);
|
||||
}
|
||||
|
||||
dest
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn __runtime_memcmp(dest: *const u8, src: *const u8, n: usize) -> i32 {
|
||||
// if (src as u32) % 4 == (dest as u32) % 4 {
|
||||
// return memcmp_aligned(dest, src, n);
|
||||
// }
|
||||
|
||||
for i in 0..n {
|
||||
if *dest.offset(i as isize) != *src.offset(i as isize) {
|
||||
return *dest.offset(i as isize) as i32 - *src.offset(i as isize) as i32;
|
||||
}
|
||||
}
|
||||
|
||||
0i32
|
||||
}
|
||||
|
||||
// pub unsafe fn memcmp_aligned(dest: *mut u8, src: *const u8, n: usize) -> i32 {
|
||||
// let mut i: isize = 0;
|
||||
|
||||
// // Prologue: set bytes in the first non-aligned word
|
||||
// let first_word_offset = (dest as u32) % 4;
|
||||
// if first_word_offset != 0 {
|
||||
// let value = *((src.offset(-(first_word_offset as isize))) as *mut u32);
|
||||
// let aligned_dest = dest.offset(-(first_word_offset as isize)) as *mut u32;
|
||||
// let mask = (1 << ((first_word_offset * 8) as u32)) - 1;
|
||||
// if (*aligned_dest & !mask) != (value & !mask) {
|
||||
// return false;
|
||||
// }
|
||||
// i += 4 - first_word_offset as isize;
|
||||
// }
|
||||
|
||||
// while i + 3 < n as isize {
|
||||
// if *((dest.offset(i)) as *mut u32) != *((src.offset(i)) as *mut u32) {
|
||||
// return false;
|
||||
// }
|
||||
// i += 4;
|
||||
// }
|
||||
|
||||
// // last part: set the final word
|
||||
// if i < n as isize {
|
||||
// let value = *((src.offset(i)) as *mut u32);
|
||||
// let dest_value = (dest.offset(i)) as *mut u32;
|
||||
// let mask = (1 << (((n as isize - i) * 8) as u32)) - 1;
|
||||
// if (*dest_value & mask) != (value & mask) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// true
|
||||
// }
|
||||
@@ -29,7 +29,7 @@ pub fn compile_riscv_asm(mut assemblies: BTreeMap<String, String>) -> String {
|
||||
|
||||
// Reduce to the code that is actually reachable from main
|
||||
// (and the objects that are referred from there)
|
||||
reachability::filter_reachable_from("main", &mut statements, &mut objects);
|
||||
reachability::filter_reachable_from("__runtime_start", &mut statements, &mut objects);
|
||||
|
||||
// Replace dynamic references to code labels
|
||||
replace_dynamic_label_references(&mut statements, &objects);
|
||||
@@ -41,7 +41,7 @@ pub fn compile_riscv_asm(mut assemblies: BTreeMap<String, String>) -> String {
|
||||
.into_iter()
|
||||
.chain([
|
||||
format!("// Set stack pointer\nx2 <=X= {stack_start};"),
|
||||
"jump main;".to_string(),
|
||||
"jump __runtime_start;".to_string(),
|
||||
])
|
||||
.chain(
|
||||
insert_data_positions(statements, &data_positions)
|
||||
@@ -552,100 +552,17 @@ fn runtime() -> &'static str {
|
||||
}
|
||||
*/
|
||||
r#"
|
||||
.globl rust_begin_unwind
|
||||
rust_begin_unwind:
|
||||
unimp
|
||||
|
||||
.globl memset@plt
|
||||
memset@plt:
|
||||
li a3, 4
|
||||
blt a2, a3, __memset_LBB5_5
|
||||
li a5, 0
|
||||
lui a3, 4112
|
||||
addi a3, a3, 257
|
||||
mul a6, a1, a3
|
||||
__memset_LBB5_2:
|
||||
add a7, a0, a5
|
||||
addi a3, a5, 4
|
||||
addi a4, a5, 7
|
||||
sw a6, 0(a7)
|
||||
mv a5, a3
|
||||
blt a4, a2, __memset_LBB5_2
|
||||
bge a3, a2, __memset_LBB5_6
|
||||
__memset_LBB5_4:
|
||||
lui a4, 16
|
||||
addi a4, a4, 257
|
||||
mul a1, a1, a4
|
||||
add a3, a3, a0
|
||||
slli a2, a2, 3
|
||||
lw a4, 0(a3)
|
||||
li a5, -1
|
||||
sll a2, a5, a2
|
||||
not a5, a2
|
||||
and a2, a2, a4
|
||||
and a1, a1, a5
|
||||
or a1, a1, a2
|
||||
sw a1, 0(a3)
|
||||
ret
|
||||
__memset_LBB5_5:
|
||||
li a3, 0
|
||||
blt a3, a2, __memset_LBB5_4
|
||||
__memset_LBB5_6:
|
||||
ret
|
||||
tail __runtime_memset
|
||||
|
||||
.globl memcpy@plt
|
||||
memcpy@plt:
|
||||
li a3, 4
|
||||
blt a2, a3, __memcpy_LBB2_5
|
||||
li a4, 0
|
||||
__memcpy_LBB2_2:
|
||||
add a3, a1, a4
|
||||
lw a6, 0(a3)
|
||||
add a7, a0, a4
|
||||
addi a3, a4, 4
|
||||
addi a5, a4, 7
|
||||
sw a6, 0(a7)
|
||||
mv a4, a3
|
||||
blt a5, a2, __memcpy_LBB2_2
|
||||
bge a3, a2, __memcpy_LBB2_6
|
||||
__memcpy_LBB2_4:
|
||||
add a1, a1, a3
|
||||
lw a1, 0(a1)
|
||||
add a3, a3, a0
|
||||
slli a2, a2, 3
|
||||
lw a4, 0(a3)
|
||||
li a5, -1
|
||||
sll a2, a5, a2
|
||||
not a5, a2
|
||||
and a2, a2, a4
|
||||
and a1, a1, a5
|
||||
or a1, a1, a2
|
||||
sw a1, 0(a3)
|
||||
ret
|
||||
__memcpy_LBB2_5:
|
||||
li a3, 0
|
||||
blt a3, a2, __memcpy_LBB2_4
|
||||
__memcpy_LBB2_6:
|
||||
ret
|
||||
tail __runtime_memcpy
|
||||
|
||||
.globl memcmp@plt
|
||||
memcmp@plt:
|
||||
beqz a2, .LBB270_3
|
||||
.LBB270_1:
|
||||
lbu a3, 0(a0)
|
||||
lbu a4, 0(a1)
|
||||
bne a3, a4, .LBB270_4
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, -1
|
||||
addi a0, a0, 1
|
||||
bnez a2, .LBB270_1
|
||||
.LBB270_3:
|
||||
li a0, 0
|
||||
ret
|
||||
.LBB270_4:
|
||||
sub a0, a3, a4
|
||||
ret
|
||||
|
||||
tail __runtime_memcmp
|
||||
"#
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,9 @@ pub fn compile_rust_to_riscv_asm(input_file: &str) -> BTreeMap<String, String> {
|
||||
name = "{}"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
runtime = {{ path = "./runtime" }}
|
||||
"#,
|
||||
Path::new(input_file).file_stem().unwrap().to_str().unwrap()
|
||||
),
|
||||
@@ -136,6 +139,21 @@ edition = "2021"
|
||||
src_file.push("lib.rs");
|
||||
fs::write(src_file, fs::read_to_string(input_file).unwrap()).unwrap();
|
||||
|
||||
let mut runtime_file = crate_dir.clone();
|
||||
runtime_file.push("runtime");
|
||||
fs::create_dir_all(&runtime_file).unwrap();
|
||||
let mut cargo_file_runtime = runtime_file.clone();
|
||||
cargo_file_runtime.push("Cargo.toml");
|
||||
fs::write(
|
||||
cargo_file_runtime.clone(),
|
||||
include_bytes!("../runtime/Cargo.toml"),
|
||||
)
|
||||
.unwrap();
|
||||
runtime_file.push("src");
|
||||
fs::create_dir(&runtime_file).unwrap();
|
||||
runtime_file.push("lib.rs");
|
||||
fs::write(runtime_file, include_bytes!("../runtime/src/lib.rs")).unwrap();
|
||||
|
||||
compile_rust_crate_to_riscv_asm(cargo_file.to_str().unwrap())
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,13 @@ fn test_double_word() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Too slow"]
|
||||
fn test_memfuncs() {
|
||||
let case = "memfuncs";
|
||||
verify_crate(case, vec![]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Too slow"]
|
||||
fn test_keccak() {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use core::alloc::{GlobalAlloc, Layout};
|
||||
use core::cell::UnsafeCell;
|
||||
use core::panic::PanicInfo;
|
||||
use core::ptr;
|
||||
|
||||
extern crate alloc;
|
||||
@@ -67,26 +66,6 @@ pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mu
|
||||
memcpy(dest, src, n)
|
||||
}
|
||||
|
||||
// TODO c is ussualy a "c int"
|
||||
pub unsafe extern "C" fn memset(s: *mut u8, c: u8, n: usize) -> *mut u8 {
|
||||
// We only access u32 because then we do not have to deal with
|
||||
// un-aligned memory access.
|
||||
// TODO this does not really enforce that the pointers are u32-aligned.
|
||||
let mut value = c as u32;
|
||||
value = value | (value << 8) | (value << 16) | (value << 24);
|
||||
let mut i: isize = 0;
|
||||
while i + 3 < n as isize {
|
||||
*((s.offset(i)) as *mut u32) = value;
|
||||
i += 4;
|
||||
}
|
||||
if i < n as isize {
|
||||
let dest_value = (s.offset(i)) as *mut u32;
|
||||
let mask = (1 << (((n as isize - i) * 8) as u32)) - 1;
|
||||
*dest_value = (*dest_value & !mask) | (value & mask);
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
// pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
|
||||
// for i in 0..n as isize {
|
||||
// let a = *s1.offset(i);
|
||||
@@ -106,11 +85,6 @@ pub unsafe extern "C" fn memset(s: *mut u8, c: u8, n: usize) -> *mut u8 {
|
||||
// i as usize
|
||||
// }
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
// Declaration of the global memory allocator
|
||||
// NOTE the user must ensure that the memory region `[0x2000_0100, 0x2000_0200]`
|
||||
// is not used by other parts of the program
|
||||
@@ -123,7 +97,7 @@ static HEAP: BumpPointerAlloc = BumpPointerAlloc {
|
||||
static LONG_STR: &str = "aoeueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> ! {
|
||||
pub fn main() -> ! {
|
||||
let mut xs = Vec::new();
|
||||
|
||||
xs.push(42);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#![no_std]
|
||||
|
||||
use core::arch::asm;
|
||||
use runtime::get_prover_input;
|
||||
|
||||
const X: &'static str = "abcdefg";
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> ! {
|
||||
pub fn main() {
|
||||
let replacement_index = get_prover_input(0) as usize;
|
||||
let replacement_value = get_prover_input(1) as u8;
|
||||
let mut x = [0; 10];
|
||||
@@ -16,14 +16,4 @@ pub extern "C" fn main() -> ! {
|
||||
let claimed_sum = get_prover_input(2) as u32;
|
||||
let computed_sum = x.iter().map(|c| *c as u32).sum();
|
||||
assert!(claimed_sum == computed_sum);
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_prover_input(index: u32) -> u32 {
|
||||
let mut value: u32;
|
||||
unsafe {
|
||||
asm!("ecall", lateout("a0") value, in("a0") index);
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#![no_std]
|
||||
|
||||
use core::arch::asm;
|
||||
use runtime::get_prover_input;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> ! {
|
||||
pub fn main() {
|
||||
let a0 = get_prover_input(0) as u64;
|
||||
let a1 = (get_prover_input(1) as u64) << 32;
|
||||
let b0 = get_prover_input(2) as u64;
|
||||
@@ -13,14 +13,4 @@ pub extern "C" fn main() -> ! {
|
||||
let c1 = ((c >> 32) & 0xffffffffu64) as u32;
|
||||
assert!(c0 == get_prover_input(4));
|
||||
assert!(c1 == get_prover_input(5));
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_prover_input(index: u32) -> u32 {
|
||||
let mut value: u32;
|
||||
unsafe {
|
||||
asm!("ecall", lateout("a0") value, in("a0") index);
|
||||
}
|
||||
value
|
||||
}
|
||||
}
|
||||
@@ -7,5 +7,6 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
tiny-keccak = { version = "2.0.2", features = ["keccak"] }
|
||||
runtime = { path = "../../../runtime" }
|
||||
|
||||
[workspace]
|
||||
@@ -3,7 +3,7 @@
|
||||
use tiny_keccak::{Hasher, Keccak};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> ! {
|
||||
pub fn main() {
|
||||
let input = b"Solidity";
|
||||
let mut output = [0u8; 32];
|
||||
let mut hasher = Keccak::v256();
|
||||
@@ -16,5 +16,4 @@ pub extern "C" fn main() -> ! {
|
||||
111, 47, 142, 70, 161, 157, 188, 119, 124, 54, 251, 12, 0,
|
||||
],
|
||||
);
|
||||
loop {}
|
||||
}
|
||||
|
||||
11
riscv/tests/riscv_data/memfuncs/Cargo.toml
Normal file
11
riscv/tests/riscv_data/memfuncs/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "memfuncs"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
runtime = { path = "../../../runtime" }
|
||||
|
||||
[workspace]
|
||||
73
riscv/tests/riscv_data/memfuncs/src/lib.rs
Normal file
73
riscv/tests/riscv_data/memfuncs/src/lib.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
#![no_std]
|
||||
|
||||
use runtime::*;
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() {
|
||||
let input = [1u8; 100];
|
||||
let mut output = [0u8; 100];
|
||||
|
||||
// Check memset accross boundaries
|
||||
unsafe {
|
||||
__runtime_memset(output.as_mut_ptr().offset(5), 2, 32);
|
||||
}
|
||||
for i in 0..5 {
|
||||
assert_eq!(
|
||||
output[i],
|
||||
0,
|
||||
);
|
||||
}
|
||||
for i in 5..=36 {
|
||||
assert_eq!(
|
||||
output[i],
|
||||
2,
|
||||
);
|
||||
}
|
||||
for i in 37..100 {
|
||||
assert_eq!(
|
||||
output[i],
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
// Check memcpy accross boundaries
|
||||
unsafe {
|
||||
__runtime_memcpy(output.as_mut_ptr().offset(5), input.as_ptr().offset(5), 32);
|
||||
}
|
||||
for i in 0..5 {
|
||||
assert_eq!(
|
||||
output[i],
|
||||
0,
|
||||
);
|
||||
}
|
||||
for i in 5..=36 {
|
||||
assert_eq!(
|
||||
output[i],
|
||||
1,
|
||||
);
|
||||
}
|
||||
for i in 37..100 {
|
||||
assert_eq!(
|
||||
output[i],
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
// Check memcmp accross boundaries
|
||||
// This doesn't work because it compiles to the unsupported
|
||||
// assembly instruction "srai".
|
||||
// unsafe {
|
||||
// assert_eq!(
|
||||
// __runtime_memcmp(output.as_ptr().offset(5), input.as_ptr().offset(5), 32),
|
||||
// 0,
|
||||
// );
|
||||
// assert_eq!(
|
||||
// __runtime_memcmp(output.as_ptr().offset(5), input.as_ptr().offset(6), 32),
|
||||
// -1,
|
||||
// );
|
||||
// assert_eq!(
|
||||
// __runtime_memcmp(output.as_ptr().offset(6), input.as_ptr().offset(5), 32),
|
||||
// 1,
|
||||
// );
|
||||
// }
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
#![no_std]
|
||||
|
||||
use core::arch::asm;
|
||||
use runtime::get_prover_input;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> ! {
|
||||
pub fn main() {
|
||||
let mut buffer = [0u32; 100];
|
||||
let proposed_sum = get_prover_input(0);
|
||||
let len = get_prover_input(1) as usize;
|
||||
@@ -13,14 +13,4 @@ pub extern "C" fn main() -> ! {
|
||||
}
|
||||
let sum: u32 = buffer[..len].iter().sum();
|
||||
assert!(sum == proposed_sum);
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_prover_input(index: u32) -> u32 {
|
||||
let mut value: u32;
|
||||
unsafe {
|
||||
asm!("ecall", lateout("a0") value, in("a0") index);
|
||||
}
|
||||
value
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
#![no_std]
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> ! {
|
||||
loop {}
|
||||
pub fn main() {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user