diff --git a/host-program/src/bin/zkm-prove.rs b/host-program/src/bin/zkm-prove.rs index 8201de48..777c6550 100644 --- a/host-program/src/bin/zkm-prove.rs +++ b/host-program/src/bin/zkm-prove.rs @@ -13,7 +13,10 @@ async fn main() -> Result<(), Box> { env_logger::try_init().unwrap_or_default(); let args: Vec = env::args().collect(); let helper = || { - log::info!("Help: {} sha2-rust | sha2-go | mem-alloc-vec", args[0]); + log::info!( + "Help: {} sha2-rust | sha2-go | mem-alloc-vec | revme", + args[0] + ); std::process::exit(-1); }; if args.len() < 2 { @@ -119,6 +122,7 @@ async fn main() -> Result<(), Box> { log::info!("ret_data: {:?}", ret_data); } "mem-alloc-vec" => log::info!("Executing the guest program successfully."), //The guest program returns nothing. + "revme" => log::info!("Executing the guest program successfully."), //The guest program returns nothing. _ => log::info!("Do nothing."), } } diff --git a/sdk/src/local/libsnark/contract.go b/sdk/src/local/libsnark/contract.go index 066f59bd..355664e4 100644 --- a/sdk/src/local/libsnark/contract.go +++ b/sdk/src/local/libsnark/contract.go @@ -150,6 +150,10 @@ library Pairing { } contract Verifier { + uint256 constant MASK = ~(uint256(0x7) << 253); + uint256 constant EMPTY_HASH = 0x3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855; + uint256 constant CIRCUIT_DIGEST = {{.Digest}}; + event VerifyEvent(address user); event Value(uint x, uint y); @@ -211,5 +215,41 @@ contract Verifier { } } + + function verifyUserData( + uint8[32] memory _userData, + uint32[8] memory _memRootBefore, + uint32[8] memory _memRootAfter + ) public pure returns (uint256) { + uint256 userData = 0; + for (uint256 i = 0; i < 32; i++) { + userData |= uint256(_userData[i]) << (8 * (31 - i)); + } + uint256 memRootBefore = 0; + for (uint256 i = 0; i < 8; i++) { + memRootBefore |= uint256(_memRootBefore[i]) << (32 * (7 - i)); + } + uint256 memRootAfter = 0; + for (uint256 i = 0; i < 8; i++) { + memRootAfter |= uint256(_memRootAfter[i]) << (32 * (7 - i)); + } + + bytes memory dataToHash = abi.encodePacked( + memRootBefore, + memRootAfter, + userData, + CIRCUIT_DIGEST, + getConstantSigmasCap() + ); + + uint256 hash_o = uint256(sha256(dataToHash)) & MASK; + uint256 hashValue = uint256(sha256(abi.encodePacked(EMPTY_HASH,hash_o))) & MASK; + + return hashValue; + } + + function getConstantSigmasCap() public pure returns (uint256[{{.Len}}] memory) { + return {{.Sigmas}}; + } } ` diff --git a/sdk/src/local/libsnark/go.mod b/sdk/src/local/libsnark/go.mod index 4417908e..5c78e728 100644 --- a/sdk/src/local/libsnark/go.mod +++ b/sdk/src/local/libsnark/go.mod @@ -10,7 +10,7 @@ require ( replace github.com/consensys/gnark v0.9.1 => github.com/zkMIPS/gnark v0.9.2-0.20240114074717-11112539ed1e -replace github.com/succinctlabs/gnark-plonky2-verifier v0.1.0 => github.com/zkMIPS/gnark-plonky2-verifier v0.0.0-20240929021913-ecd070f3d885 +replace github.com/succinctlabs/gnark-plonky2-verifier v0.1.0 => github.com/zkMIPS/gnark-plonky2-verifier v0.0.0-20241014144329-df6d28e3f777 require ( github.com/Microsoft/go-winio v0.6.1 // indirect diff --git a/sdk/src/local/libsnark/go.sum b/sdk/src/local/libsnark/go.sum index a8971985..82e09a01 100644 --- a/sdk/src/local/libsnark/go.sum +++ b/sdk/src/local/libsnark/go.sum @@ -183,8 +183,8 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRT github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/zkMIPS/gnark v0.9.2-0.20240114074717-11112539ed1e h1:T2nl8q9iCxNe5ay+D0OAC+HrQaIj5PmzkbJVuJbn7lk= github.com/zkMIPS/gnark v0.9.2-0.20240114074717-11112539ed1e/go.mod h1:s681Fp+KgDAK1Ix0FQgTMkmGOr9yjJLF9M8DOt5TKtA= -github.com/zkMIPS/gnark-plonky2-verifier v0.0.0-20240929021913-ecd070f3d885 h1:CzLGe+Bht/H1MjddnFBgve/spNDxTvv2+Dv4yMecUbQ= -github.com/zkMIPS/gnark-plonky2-verifier v0.0.0-20240929021913-ecd070f3d885/go.mod h1:kld+gvw6wy/QS5D+kIb6bWOeWgu/eKZ7krBvbEBdnZ8= +github.com/zkMIPS/gnark-plonky2-verifier v0.0.0-20241014144329-df6d28e3f777 h1:2VojZJszH8dsUon5yIDhZP8evK6vL8fFTN567jZ1rkg= +github.com/zkMIPS/gnark-plonky2-verifier v0.0.0-20241014144329-df6d28e3f777/go.mod h1:kld+gvw6wy/QS5D+kIb6bWOeWgu/eKZ7krBvbEBdnZ8= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= diff --git a/sdk/src/local/libsnark/snark_prover.go b/sdk/src/local/libsnark/snark_prover.go index de76cb68..1e9dea61 100644 --- a/sdk/src/local/libsnark/snark_prover.go +++ b/sdk/src/local/libsnark/snark_prover.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "io" "path/filepath" "text/template" @@ -173,7 +174,7 @@ func (obj *SnarkProver) groth16ProofWithCache(r1cs constraint.ConstraintSystem, return nil } -func (obj *SnarkProver) generateVerifySol(outputDir string) error { +func (obj *SnarkProver) generateVerifySol(inputDir, outputDir string) error { tmpl, err := template.New("contract").Parse(Gtemplate) if err != nil { return err @@ -184,7 +185,10 @@ func (obj *SnarkProver) generateVerifySol(outputDir string) error { Beta string Gamma string Delta string + Digest string Gamma_abc string + Sigmas string + Len int } var config VerifyingKeyConfig @@ -198,6 +202,39 @@ func (obj *SnarkProver) generateVerifySol(outputDir string) error { for k, v := range vk.G1.K { config.Gamma_abc += fmt.Sprint(" vk.gamma_abc[", k, "] = Pairing.G1Point(uint256(", v.X.String(), "), uint256(", v.Y.String(), "));\n") } + + // constant + file, err := os.Open(inputDir + "/block_public_inputs.json") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + defer file.Close() + + rawBytes, _ := io.ReadAll(file) + var publicInputsOnly types.PublicInputsOnly + err = json.Unmarshal(rawBytes, &publicInputsOnly) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + piData := publicInputsOnly.PublicInputs[48:] + circuitDIgest := obj.combineToBigInt(piData, 0) + config.Digest = circuitDIgest.String() + + l := len(piData)/4 - 1 + config.Len = l + + config.Sigmas = fmt.Sprint("[\n") + for i := 0; i < l; i++ { + v := obj.combineToBigInt(piData, i*4+4) + config.Sigmas += fmt.Sprint("\t\t\t", v) + if i < l-1 { + config.Sigmas += fmt.Sprint(",\n") + } + } + config.Sigmas += fmt.Sprint("\n\t\t]") + var buf bytes.Buffer err = tmpl.Execute(&buf, config) if err != nil { @@ -212,12 +249,25 @@ func (obj *SnarkProver) generateVerifySol(outputDir string) error { return nil } +func (obj *SnarkProver) combineToBigInt(data []uint64, idx int) *big.Int { + result := new(big.Int) + + for i := 0; i < 4; i++ { + part := new(big.Int).SetUint64(data[idx+i]) + + part.Lsh(part, uint(64*(3-i))) + result.Add(result, part) + } + + return result +} + func (obj *SnarkProver) Prove(inputdir string, outputdir string) error { if err := obj.init_circuit_keys(inputdir); err != nil { return err } - if err := obj.generateVerifySol(outputdir); err != nil { + if err := obj.generateVerifySol(inputdir, outputdir); err != nil { return err } diff --git a/sdk/src/local/util.rs b/sdk/src/local/util.rs index a82ea3bd..6d6e24cb 100644 --- a/sdk/src/local/util.rs +++ b/sdk/src/local/util.rs @@ -221,6 +221,12 @@ pub fn prove_multi_seg_common( let public_values_file = File::create(outdir_path.join("public_values.json"))?; serde_json::to_writer(&public_values_file, &updated_agg_public_values)?; + let block_public_inputs = serde_json::json!({ + "public_inputs": block_proof.public_inputs, + }); + let block_public_inputs_file = File::create(outdir_path.join("block_public_inputs.json"))?; + serde_json::to_writer(&block_public_inputs_file, &block_public_inputs)?; + total_timing.filter(Duration::from_millis(100)).print(); result }