diff --git a/.gitignore b/.gitignore index 1cfae000..a8710ed8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /Cargo.lock /output /examples/target +**/.DS_Store diff --git a/prover/examples/sha2-go/go.mod b/prover/examples/sha2-go/go.mod new file mode 100644 index 00000000..0a8eab78 --- /dev/null +++ b/prover/examples/sha2-go/go.mod @@ -0,0 +1,7 @@ +module sha2-go + +go 1.22.5 + +replace github.com/zkMIPS/zkm/go-runtime/zkm_runtime => ../../../go-runtime/zkm_runtime + +require github.com/zkMIPS/zkm/go-runtime/zkm_runtime v0.0.0-20240817102429-2faba0888c02 diff --git a/prover/examples/sha2-go/main.go b/prover/examples/sha2-go/main.go new file mode 100644 index 00000000..6e794380 --- /dev/null +++ b/prover/examples/sha2-go/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "bytes" + "crypto/sha256" + "log" + + "github.com/zkMIPS/zkm/go-runtime/zkm_runtime" +) + +type DataId uint32 + +// use iota to create enum +const ( + TYPE1 DataId = iota + TYPE2 + TYPE3 +) + +type Data struct { + Input1 [10]byte + Input2 uint8 + Input3 int8 + Input4 uint16 + Input5 int16 + Input6 uint32 + Input7 int32 + Input8 uint64 + Input9 int64 + Input10 []byte + Input11 DataId + Input12 string +} + +func main() { + a := zkm_runtime.Read[Data]() + + data := []byte(a.Input12) + hash := sha256.Sum256(data) + + assertEqual(hash[:], a.Input10) + + zkm_runtime.Commit[Data](a) +} + +func assertEqual(a []byte, b []byte) { + if !bytes.Equal(a, b) { + log.Fatal("%x != %x", a, b) + } +} diff --git a/prover/examples/sha2/Cargo.lock b/prover/examples/sha2-rust/Cargo.lock similarity index 100% rename from prover/examples/sha2/Cargo.lock rename to prover/examples/sha2-rust/Cargo.lock diff --git a/prover/examples/sha2/Cargo.toml b/prover/examples/sha2-rust/Cargo.toml similarity index 90% rename from prover/examples/sha2/Cargo.toml rename to prover/examples/sha2-rust/Cargo.toml index 0ac8926c..b9dedc44 100644 --- a/prover/examples/sha2/Cargo.toml +++ b/prover/examples/sha2-rust/Cargo.toml @@ -1,7 +1,7 @@ [workspace] [package] version = "0.1.0" -name = "sha2-bench" +name = "sha2-rust" edition = "2021" [dependencies] diff --git a/prover/examples/sha2/rust-toolchain.toml b/prover/examples/sha2-rust/rust-toolchain.toml similarity index 55% rename from prover/examples/sha2/rust-toolchain.toml rename to prover/examples/sha2-rust/rust-toolchain.toml index 6650ae6e..64c5f280 100644 --- a/prover/examples/sha2/rust-toolchain.toml +++ b/prover/examples/sha2-rust/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2023-03-06-x86_64-unknown-linux-gnu" +channel = "nightly-2023-04-06-x86_64-unknown-linux-gnu" targets = ["mips-unknown-linux-musl"] profile = "minimal" diff --git a/prover/examples/sha2/src/main.rs b/prover/examples/sha2-rust/src/main.rs similarity index 100% rename from prover/examples/sha2/src/main.rs rename to prover/examples/sha2-rust/src/main.rs diff --git a/prover/examples/zkmips.rs b/prover/examples/zkmips.rs index df7548aa..d9f0a0ea 100644 --- a/prover/examples/zkmips.rs +++ b/prover/examples/zkmips.rs @@ -247,10 +247,12 @@ fn prove_multi_seg_common( result } -fn prove_sha2_bench() { +fn prove_sha2_rust() { // 1. split ELF into segs let elf_path = env::var("ELF_PATH").expect("ELF file is missing"); let seg_path = env::var("SEG_OUTPUT").expect("Segment output path is missing"); + let seg_size = env::var("SEG_SIZE").unwrap_or("0".to_string()); + let seg_size = seg_size.parse::<_>().unwrap_or(0); let mut state = load_elf_with_patch(&elf_path, vec![]); // load input @@ -268,14 +270,60 @@ fn prove_sha2_bench() { log::info!("private input value: {:X?}", private_input); state.add_input_stream(&private_input); - let (total_steps, mut state) = split_prog_into_segs(state, &seg_path, "", 0); + let (total_steps, mut state) = split_prog_into_segs(state, &seg_path, "", seg_size); let value = state.read_public_values::<[u8; 32]>(); log::info!("public value: {:X?}", value); log::info!("public value: {} in hex", hex::encode(value)); - let seg_file = format!("{seg_path}/{}", 0); - prove_single_seg_common(&seg_file, "", "", "", total_steps); + let mut seg_num = 1usize; + if seg_size != 0 { + seg_num = (total_steps + seg_size - 1) / seg_size; + } + + prove_multi_seg_common(&seg_path, "", "", "", seg_size, seg_num, 0).unwrap() +} + +fn prove_sha2_go() { + // 1. split ELF into segs + let elf_path = env::var("ELF_PATH").expect("ELF file is missing"); + let seg_path = env::var("SEG_OUTPUT").expect("Segment output path is missing"); + let seg_size = env::var("SEG_SIZE").unwrap_or("0".to_string()); + let seg_size = seg_size.parse::<_>().unwrap_or(0); + + let mut state = load_elf_with_patch(&elf_path, vec![]); + // load input + let args = env::var("ARGS").unwrap_or("data-to-hash".to_string()); + // assume the first arg is the hash output(which is a public input), and the second is the input. + let args: Vec<&str> = args.split_whitespace().collect(); + assert_eq!(args.len(), 2); + + let mut data = Data::new(); + + // Fill in the input data + data.input10 = hex::decode(args[0]).unwrap(); + data.input12 = args[1].to_string(); + + state.add_input_stream(&data); + log::info!( + "enum {} {} {}", + DataId::TYPE1 as u8, + DataId::TYPE2 as u8, + DataId::TYPE3 as u8 + ); + log::info!("public input: {:X?}", data); + + let (total_steps, mut state) = split_prog_into_segs(state, &seg_path, "", seg_size); + + let value = state.read_public_values::(); + log::info!("public value: {:X?}", value); + + let mut seg_num = 1usize; + if seg_size != 0 { + seg_num = (total_steps + seg_size - 1) / seg_size; + } + + prove_multi_seg_common(&seg_path, "", "", "", seg_size, seg_num, 0).unwrap() } fn prove_revm() { @@ -397,7 +445,8 @@ fn prove_add_example() { fn prove_host() { let host_program = env::var("HOST_PROGRAM").expect("host_program name is missing"); match host_program.as_str() { - "sha2_bench" => prove_sha2_bench(), + "sha2_rust" => prove_sha2_rust(), + "sha2_go" => prove_sha2_go(), "revm" => prove_revm(), "add_example" => prove_add_example(), _ => log::error!("Host program {} is not supported!", host_program),