diff --git a/README.md b/README.md index 538c591f..c77fba00 100644 --- a/README.md +++ b/README.md @@ -114,8 +114,10 @@ cd zkm-project-template/host-program > 2. There are two script programs available: run_local_proving.sh and run_network_proving.sh. These scripts facilitate the generation of proofs on the local machine and over the proof network, respectively. -> 3. There are three guest programs(sha2-rust, sha2-go, mem-alloc-vec), each capable of generating a SNARK proof on a machine -equipped with an AMD EPYC 7R13 processor and 250GB of memory. The following will use sha2-rust as an example to demonstrate local and network proofs. +> 3. There are four guest programs(sha2-rust, sha2-go, mem-alloc-vec,revme). The following will use sha2-rust and revme as an example to demonstrate local and network proofs. + +> 4. If the environmental variable `PROOF_RESULTS_PATH` is not set, the proof results file will be saved in zkm-project-template/contracts/{src, verifier}; if the environmental variable `PROOF_RESULTS_PATH` is set, after the proof is completed, the proof results file needs to be copied from from 'PROOF_RESULTS_PATH'/{src, verifier} to the corresponding zkm-project-template/contracts/{src, verifier}. + > [!WARNING] > The environmental variable `SEG_SIZE` in the run-xxx_proving.sh affects the final proof generation. @@ -124,7 +126,7 @@ equipped with an AMD EPYC 7R13 processor and 250GB of memory. The following will > When generating proofs on the local machine, if the log shows "!!!*******seg_num: 1", please reduce SEG_SIZE or increase the input. If generating proofs through the proof network, SEG_SIZE must be within the range [65536, 262144]. -### Example : `sha2-rust` +### Example 1 : `sha2-rust` This host program sends the private input pri_input = vec![5u8; 1024] and its hash (hash(pri_input)) to the guest program for verification of the hash value. @@ -290,3 +292,29 @@ Sensitive values saved to: /mnt/data/zkm-project-template/contracts/cache/verifi ``` For more details, please refer to [this](contracts/README.md) guide. + +### Example 2 : `revme` + +The revme guest program takes a block data as input and its running is as same as the sha2-rust. Here, the focus is on explaining how to generate block data(the revme's input). + +#### Generating the public input about a specific block + +> [!NOTE] +> The local node connects ZKM test chain in the following example. You must use the Eth-Compatible local node. + +```sh +cd ~ +git clone https://github.com/zkMIPS/revme +cd revme +RPC_URL=http://localhost:8545 CHAIN_ID=1337 BLOCK_NO=244 RUST_LOG=debug SUITE_JSON_PATH=./test-vectors/244.json cargo run --example process +``` + +If successfully, it will generate `244.json` in the path test-vectors + +```sh +cp test-vectors/244.json zkm-project-template/host-program/test-vectors/ +``` + +Next, you need to edit the `JSON_PATH` variable in the [`run-local-proving.sh`](host-program/run-local-proving.sh) or [`run-network-proving.sh`](host-program/run-network-proving.sh) to match the name of the JSON file mentioned above. + +Then, you can execute the run-xxx-proving.sh by following the steps outlined in `Example 1: sha2-rust`. \ No newline at end of file diff --git a/contracts/src/verifier.sol b/contracts/src/verifier.sol index e53cb5a8..271232cd 100644 --- a/contracts/src/verifier.sol +++ b/contracts/src/verifier.sol @@ -61,13 +61,13 @@ library Pairing { input[1] = p.Y; input[2] = s; bool success; - + assembly { success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } - + require (success); } /// @return the result of computing the pairing check @@ -90,13 +90,13 @@ library Pairing { } uint[1] memory out; bool success; - + assembly { success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) // Use "invalid" to make gas estimation work // switch success case 0 { invalid() } } - + require(success,"no"); return out[0] != 0; } @@ -148,6 +148,10 @@ library Pairing { } contract Verifier { + uint256 constant MASK = ~(uint256(0x7) << 253); + uint256 constant EMPTY_HASH = 0x3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855; + uint256 constant CIRCUIT_DIGEST = 17524917735085582509473322861927874526127848298611193781519203348111540784568; + event VerifyEvent(address user); event Value(uint x, uint y); @@ -165,19 +169,19 @@ contract Verifier { Pairing.G1Point c; } function verifyingKey() pure internal returns (VerifyingKey memory vk) { - vk.alpha = Pairing.G1Point(uint256(5238594224415803428903552163224573733888230552897477768815476746088817694665), uint256(16328026879972510425634956651757872870689877162649076255746551787054864220355)); - vk.beta = Pairing.G2Point([uint256(20324176648632662611169376759002700320443304453272693285118269429660227814847), uint256(9549073425549497017615537849571476830587596656015613611017956266089308903531)], [uint256(9337569445850381137129018980746968145714905364224388186337838316616854951754), uint256(3513913997312605870476238882256631130522705321741945577205945205501138882378)]); - vk.gamma = Pairing.G2Point([uint256(15161880990256081123123373723003760974001614786036869673944011467642681350273), uint256(9163286039211553980285501179844267362965858818412298332978707992237561271164)], [uint256(8680437061849217529408110466997375226429075645841820069852588072607969726492), uint256(18800549715559362373103731617654666483740554675125608300590590295497678086269)]); - vk.delta = Pairing.G2Point([uint256(5084358276310810830336673597459062196788688825694978068951204319614533728072), uint256(2821074186679041829554082022899130273208453252341587777698126697055071930462)], [uint256(21456200227661305460882352714936824169326675407976258160476432406731382755331), uint256(7296447269627149028431860329913792045260832865974902439493666631626649609193)]); + vk.alpha = Pairing.G1Point(uint256(4982840985977509480812696446748055946734515908139415073223361588673361263746), uint256(8712150437299664934793155504800743464028309588231747319088718049163058504378)); + vk.beta = Pairing.G2Point([uint256(14644847491060364109480040637526345932168168023485200270880573723303997401430), uint256(6775420302490570505302079782352798472495089461815319569111358423389688511258)], [uint256(14768767847587643701090831715662879751600874573066085500496772126134950836854), uint256(240437156120544871266428605167538236442109586608972230783814470863300438827)]); + vk.gamma = Pairing.G2Point([uint256(7262210795700233819627126529411641564304118216220826693309624003838669118557), uint256(17968365474447290552942753834244607172785018962023497431395501373062750769088)], [uint256(20236512178005743879072938503706731346788846934024160084859279719418824582905), uint256(21482178354445909306461993182701005930359221724872119005518668975905484364020)]); + vk.delta = Pairing.G2Point([uint256(1429989016433393031270355281347460626641102112248176356804534174800828327904), uint256(8658924682454037491287711579335854754277930237325482595536833570576568002546)], [uint256(6666320311792476308297678246169834119738677804991811576981285704354255423405), uint256(17225692118650814592746316412064011994785803400777901648568774307469594781516)]); vk.gamma_abc = new Pairing.G1Point[](3); - vk.gamma_abc[0] = Pairing.G1Point(uint256(12714166869634051746888443609265681012145928347211427641836759112149836905420), uint256(11793561626188782503504016672377056451459939677293717125670005645761619823785)); - vk.gamma_abc[1] = Pairing.G1Point(uint256(12843888235824976460769557467680522067504783112310502594161600686576288283623), uint256(21500613568509565203375400055914065701770933353363264002526901521910619984442)); - vk.gamma_abc[2] = Pairing.G1Point(uint256(8046476541142506270894150739369274117716896582126953035714106843523496457093), uint256(11973219905447798721811213848944330597161079598635743680895679571487377395568)); + vk.gamma_abc[0] = Pairing.G1Point(uint256(658688055398885923946239798304191006171364785528162641914664772011403932614), uint256(16627251529150893079116090723842709162209343897331682563491207763133727729949)); + vk.gamma_abc[1] = Pairing.G1Point(uint256(17533717551801610611963983357502065482287525214778437011670149217505961606170), uint256(6945694641534038337990336721326850919360048910929658061971010569206119522556)); + vk.gamma_abc[2] = Pairing.G1Point(uint256(13525035671734603893608933762469327796081853408677259439579741391855268192799), uint256(10191107221118371707862430176671506476078342119397430622030687829974682775664)); } function verify(uint[2] memory input, Proof memory proof, uint[2] memory proof_commitment) public view returns (uint) { uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617; - + VerifyingKey memory vk = verifyingKey(); require(input.length + 1 == vk.gamma_abc.length); // Compute the linear combination vk_x @@ -201,13 +205,67 @@ contract Verifier { return 0; } - function verifyTx(Proof memory proof, uint[2] memory input,uint[2] memory proof_commitment) public returns (bool r) { + function verifyTx( + Proof memory proof, uint[2] memory input + ,uint[2] memory proof_commitment) public returns (bool r) { + if (verify(input, proof , proof_commitment) == 0) { emit VerifyEvent(msg.sender); return true; } else { return false; } - + } -} + + function calculatePublicInput( + bytes memory _userData, + uint32[8] memory _memRootBefore, + uint32[8] memory _memRootAfter + ) public pure returns (uint256) { + bytes32 userData = sha256(_userData); + + 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[16] memory) { + return [ + 91383584712019272681377229182172954852761112840230485576576219640999915415908, + 59255968443781732618398964440087269720283395714373383774650673994811543257891, + 43522785206513529710314565972458653794534948943367780523535399673207256542667, + 40342750684549940679043033475171365072773076053340772573915667403010979823501, + 27317612392857105781687183282424868606341901129358521256675721204392832410439, + 43307034001377032728710254791751651528006774034804994236242404941502133194788, + 96847759610594182728575775013319360940143540443603110434763689062442262276056, + 103816866397357498456560831382884881537689393646419658130688223819092141266482, + 92927370392150370847456421756552282870716539874859278967093815334673659047245, + 48196270063118112994752430351531600491056188761932189573202142214229711823214, + 72300508929423173342535162393269108469073018007670992928238766269813213409236, + 96435373004420944780577491829986863106913456501189307806899876787207854460461, + 49751597273171012664300923220213149590083424576410050544981754459509775460226, + 34852111753877916137017959036830401094053286275843684490553560491310958812859, + 50803581021794237060724898598173476602507622641970514917690126680609140114800, + 97509144034546411327314284027738859064756953812076402994654732676369028259664 + ]; + } +} \ No newline at end of file diff --git a/contracts/test/verifier.t.sol b/contracts/test/verifier.t.sol index 7e87eaf3..d4b5ae6b 100644 --- a/contracts/test/verifier.t.sol +++ b/contracts/test/verifier.t.sol @@ -56,6 +56,7 @@ struct VerifierProof { PairingG1Point C ; } + contract VerifierTest is Test { using stdJson for string; @@ -119,4 +120,45 @@ contract VerifierTest is Test { } + function test_ValidPublicInputs() public view { + string memory root = vm.projectRoot(); + string memory path1 = string.concat(root, "/verifier/snark_proof_with_public_inputs.json"); + string memory json1 = vm.readFile(path1); + bytes memory publicWitness = json1.parseRaw(".PublicWitness"); + string[] memory pubwit = abi.decode(publicWitness, ( string[])); + uint256 [2] memory input; + for (uint256 i = 0; i < pubwit.length; i++ ){ + input[i] = vm.parseUint(pubwit[i]); //--> uint256 + } + + string memory path = string.concat(root, "/verifier/public_inputs.json"); + string memory json = vm.readFile(path); + + bytes memory rootBefore = json.parseRaw(".roots_before.root"); + uint32[] memory rootBe = abi.decode(rootBefore, ( uint32[])); + uint32[8] memory rootb; + for (uint256 i = 0; i < rootBe.length; i++ ){ + rootb[i] = rootBe[i]; + } + + bytes memory rootAfter = json.parseRaw(".roots_after.root"); + uint32[] memory rootAf = abi.decode(rootAfter, ( uint32[])); + uint32[8] memory roota; + for (uint256 i = 0; i < rootAf.length; i++ ){ + roota[i] = rootAf[i]; + } + + bytes memory userdata = json.parseRaw(".userdata"); + uint8[] memory dataU = abi.decode(userdata, ( uint8[])); + bytes memory data = new bytes(dataU.length); + for (uint256 i = 0; i < data.length; i++) { + data[i] = bytes1(dataU[i]); + } + + + uint256 returnNum = verifier.calculatePublicInput(data, rootb, roota); + assert(returnNum == input[0]); + + } + } diff --git a/contracts/verifier/public_inputs.json b/contracts/verifier/public_inputs.json new file mode 100644 index 00000000..46d8fb89 --- /dev/null +++ b/contracts/verifier/public_inputs.json @@ -0,0 +1 @@ +{"roots_before":{"root":[3180437513,2269175112,3980585591,1336417138,3868846496,1961193041,1556548794,1348838317]},"roots_after":{"root":[2706326830,1994368865,3808172320,3128503797,3298745588,256064002,3617964268,2235077062]},"userdata":[210,10,0,0,0,0,0,0,123,34,95,105,110,102,111,34,58,110,117,108,108,44,34,99,104,97,105,110,95,105,100,34,58,51,50,51,56,50,44,34,101,110,118,34,58,123,34,99,117,114,114,101,110,116,67,111,105,110,98,97,115,101,34,58,34,48,120,57,49,51,57,101,101,53,52,53,48,102,100,51,98,48,100,48,55,101,51,97,54,50,51,101,101,53,101,51,100,102,48,49,51,98,102,100,101,97,55,34,44,34,99,117,114,114,101,110,116,68,105,102,102,105,99,117,108,116,121,34,58,34,48,120,48,34,44,34,99,117,114,114,101,110,116,71,97,115,76,105,109,105,116,34,58,34,48,120,49,99,57,99,51,56,48,34,44,34,99,117,114,114,101,110,116,78,117,109,98,101,114,34,58,34,48,120,51,48,99,48,100,34,44,34,99,117,114,114,101,110,116,84,105,109,101,115,116,97,109,112,34,58,34,48,120,54,54,101,102,51,101,52,101,34,44,34,99,117,114,114,101,110,116,66,97,115,101,70,101,101,34,58,34,48,120,55,34,44,34,112,114,101,118,105,111,117,115,72,97,115,104,34,58,34,48,120,54,102,99,99,56,51,54,50,55,49,100,100,55,101,49,54,49,97,55,53,57,97,50,102,50,102,49,54,99,55,48,57,100,52,49,49,50,101,52,101,53,56,51,53,55,98,99,97,98,52,49,55,102,54,54,54,102,102,56,55,53,55,51,57,34,44,34,99,117,114,114,101,110,116,82,97,110,100,111,109,34,58,34,48,120,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,34,44,34,99,117,114,114,101,110,116,66,101,97,99,111,110,82,111,111,116,34,58,34,48,120,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,34,44,34,99,117,114,114,101,110,116,87,105,116,104,100,114,97,119,97,108,115,82,111,111,116,34,58,34,48,120,53,54,101,56,49,102,49,55,49,98,99,99,53,53,97,54,102,102,56,51,52,53,101,54,57,50,99,48,102,56,54,101,53,98,52,56,101,48,49,98,57,57,54,99,97,100,99,48,48,49,54,50,50,102,98,53,101,51,54,51,98,52,50,49,34,44,34,112,97,114,101,110,116,66,108,111,98,71,97,115,85,115,101,100,34,58,34,48,120,53,50,48,56,34,44,34,112,97,114,101,110,116,69,120,99,101,115,115,66,108,111,98,71,97,115,34,58,34,48,120,53,50,48,56,34,125,44,34,112,114,101,34,58,123,34,48,120,49,56,100,98,55,100,102,53,102,51,48,97,97,102,54,98,52,102,49,53,98,50,52,50,99,48,55,99,101,54,50,102,102,97,50,102,51,51,49,49,34,58,123,34,98,97,108,97,110,99,101,34,58,34,48,120,49,99,57,100,49,50,48,49,48,53,54,48,48,48,34,44,34,99,111,100,101,34,58,34,48,120,34,44,34,110,111,110,99,101,34,58,34,48,120,48,34,44,34,115,116,111,114,97,103,101,34,58,123,125,125,44,34,48,120,57,49,51,57,101,101,53,52,53,48,102,100,51,98,48,100,48,55,101,51,97,54,50,51,101,101,53,101,51,100,102,48,49,51,98,102,100,101,97,55,34,58,123,34,98,97,108,97,110,99,101,34,58,34,48,120,50,98,48,55,55,101,98,97,99,53,102,50,53,50,100,49,101,99,99,34,44,34,99,111,100,101,34,58,34,48,120,34,44,34,110,111,110,99,101,34,58,34,48,120,102,34,44,34,115,116,111,114,97,103,101,34,58,123,125,125,44,34,48,120,97,52,56,50,97,101,55,100,55,53,51,98,51,51,99,98,48,54,102,100,54,56,55,50,52,52,51,101,57,48,50,99,98,54,98,101,101,53,57,50,34,58,123,34,98,97,108,97,110,99,101,34,58,34,48,120,49,48,57,56,51,100,54,101,48,97,48,102,57,51,52,56,99,53,48,34,44,34,99,111,100,101,34,58,34,48,120,34,44,34,110,111,110,99,101,34,58,34,48,120,49,97,34,44,34,115,116,111,114,97,103,101,34,58,123,125,125,125,44,34,112,111,115,116,34,58,123,34,83,104,97,110,103,104,97,105,34,58,91,123,34,101,120,112,101,99,116,69,120,99,101,112,116,105,111,110,34,58,110,117,108,108,44,34,105,110,100,101,120,101,115,34,58,123,34,100,97,116,97,34,58,48,44,34,103,97,115,34,58,48,44,34,118,97,108,117,101,34,58,48,125,44,34,104,97,115,104,34,58,34,48,120,99,102,48,54,54,53,99,98,102,97,50,56,57,48,97,57,102,101,48,53,100,101,99,48,50,55,102,102,99,97,53,48,102,50,50,57,97,52,49,52,99,54,49,48,51,48,48,52,97,49,49,55,102,49,100,102,101,57,53,50,99,52,53,98,34,44,34,112,111,115,116,83,116,97,116,101,34,58,123,34,48,120,49,56,100,98,55,100,102,53,102,51,48,97,97,102,54,98,52,102,49,53,98,50,52,50,99,48,55,99,101,54,50,102,102,97,50,102,51,51,49,49,34,58,123,34,98,97,108,97,110,99,101,34,58,34,48,120,49,100,53,101,99,97,101,101,53,98,98,48,48,48,34,44,34,99,111,100,101,34,58,34,48,120,34,44,34,110,111,110,99,101,34,58,34,48,120,48,34,44,34,115,116,111,114,97,103,101,34,58,123,125,125,44,34,48,120,97,52,56,50,97,101,55,100,55,53,51,98,51,51,99,98,48,54,102,100,54,56,55,50,52,52,51,101,57,48,50,99,98,54,98,101,101,53,57,50,34,58,123,34,98,97,108,97,110,99,101,34,58,34,48,120,49,48,57,56,51,100,53,102,56,98,53,50,56,99,55,53,101,49,56,34,44,34,99,111,100,101,34,58,34,48,120,34,44,34,110,111,110,99,101,34,58,34,48,120,49,98,34,44,34,115,116,111,114,97,103,101,34,58,123,125,125,44,34,48,120,57,49,51,57,101,101,53,52,53,48,102,100,51,98,48,100,48,55,101,51,97,54,50,51,101,101,53,101,51,100,102,48,49,51,98,102,100,101,97,55,34,58,123,34,98,97,108,97,110,99,101,34,58,34,48,120,50,98,48,55,55,101,98,100,50,57,50,48,56,52,49,98,101,99,99,34,44,34,99,111,100,101,34,58,34,48,120,34,44,34,110,111,110,99,101,34,58,34,48,120,102,34,44,34,115,116,111,114,97,103,101,34,58,123,125,125,125,44,34,108,111,103,115,34,58,34,48,120,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,34,44,34,116,120,98,121,116,101,115,34,58,34,48,120,55,98,50,50,54,51,54,49,54,99,54,99,54,53,55,50,50,50,51,97,50,50,51,48,55,56,54,49,51,52,51,56,51,50,54,49,54,53,51,55,54,52,51,55,51,53,51,51,54,50,51,51,51,51,54,51,54,50,51,48,51,54,54,54,54,52,51,54,51,56,51,55,51,50,51,52,51,52,51,51,54,53,51,57,51,48,51,50,54,51,54,50,51,54,54,50,54,53,54,53,51,53,51,57,51,50,50,50,50,99,50,50,54,55,54,49,55,51,53,102,54,99,54,57,54,100,54,57,55,52,50,50,51,97,51,50,51,49,51,48,51,48,51,48,50,99,50,50,54,55,54,49,55,51,53,102,55,48,55,50,54,57,54,51,54,53,50,50,51,97,50,50,51,48,55,56,51,55,51,55,51,51,51,53,51,57,51,52,51,48,51,55,50,50,50,99,50,50,55,52,55,50,54,49,54,101,55,51,54,49,54,51,55,52,53,102,55,52,54,102,50,50,51,97,50,50,51,48,55,56,51,49,51,56,54,52,54,50,51,55,54,52,54,54,51,53,54,54,51,51,51,48,54,49,54,49,54,54,51,54,54,50,51,52,54,54,51,49,51,53,54,50,51,50,51,52,51,50,54,51,51,48,51,55,54,51,54,53,51,54,51,50,54,54,54,54,54,49,51,50,54,54,51,51,51,51,51,49,51,49,50,50,50,99,50,50,55,54,54,49,54,99,55,53,54,53,50,50,51,97,50,50,51,48,55,56,54,51,51,49,54,50,51,56,54,53,54,52,51,53,51,54,51,53,51,48,51,48,51,48,50,50,50,99,50,50,54,52,54,49,55,52,54,49,50,50,51,97,50,50,51,48,55,56,50,50,50,99,50,50,54,101,54,102,54,101,54,51,54,53,50,50,51,97,51,50,51,54,50,99,50,50,54,51,54,56,54,49,54,57,54,101,53,102,54,57,54,52,50,50,51,97,51,51,51,50,51,51,51,56,51,50,50,99,50,50,54,49,54,51,54,51,54,53,55,51,55,51,53,102,54,99,54,57,55,51,55,52,50,50,51,97,53,98,53,100,50,99,50,50,54,55,54,49,55,51,53,102,55,48,55,50,54,57,54,102,55,50,54,57,55,52,55,57,53,102,54,54,54,53,54,53,50,50,51,97,50,50,51,48,55,56,51,55,51,55,51,51,51,53,51,57,51,52,51,48,51,48,50,50,50,99,50,50,54,50,54,99,54,102,54,50,53,102,54,56,54,49,55,51,54,56,54,53,55,51,50,50,51,97,53,98,53,100,50,99,50,50,54,100,54,49,55,56,53,102,54,54,54,53,54,53,53,102,55,48,54,53,55,50,53,102,54,50,54,99,54,102,54,50,53,102,54,55,54,49,55,51,50,50,51,97,54,101,55,53,54,99,54,99,50,99,50,50,54,49,55,53,55,52,54,56,54,102,55,50,54,57,55,97,54,49,55,52,54,57,54,102,54,101,53,102,54,99,54,57,55,51,55,52,50,50,51,97,54,101,55,53,54,99,54,99,55,100,34,125,93,125,44,34,116,114,97,110,115,97,99,116,105,111,110,34,58,123,34,100,97,116,97,34,58,91,34,48,120,34,93,44,34,103,97,115,76,105,109,105,116,34,58,91,34,48,120,53,50,48,56,34,93,44,34,103,97,115,80,114,105,99,101,34,58,34,48,120,55,55,51,53,57,52,48,55,34,44,34,110,111,110,99,101,34,58,34,48,120,49,97,34,44,34,115,101,99,114,101,116,75,101,121,34,58,34,48,120,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,34,44,34,115,101,110,100,101,114,34,58,34,48,120,97,52,56,50,97,101,55,100,55,53,51,98,51,51,99,98,48,54,102,100,54,56,55,50,52,52,51,101,57,48,50,99,98,54,98,101,101,53,57,50,34,44,34,116,111,34,58,34,48,120,49,56,100,98,55,100,102,53,102,51,48,97,97,102,54,98,52,102,49,53,98,50,52,50,99,48,55,99,101,54,50,102,102,97,50,102,51,51,49,49,34,44,34,118,97,108,117,101,34,58,91,34,48,120,99,49,98,56,101,100,53,54,53,48,48,48,34,93,44,34,109,97,120,70,101,101,80,101,114,71,97,115,34,58,34,48,120,49,55,52,56,55,54,101,56,48,48,34,44,34,109,97,120,80,114,105,111,114,105,116,121,70,101,101,80,101,114,71,97,115,34,58,34,48,120,55,55,51,53,57,52,48,48,34,44,34,97,99,99,101,115,115,76,105,115,116,115,34,58,91,91,93,93,44,34,98,108,111,98,86,101,114,115,105,111,110,101,100,72,97,115,104,101,115,34,58,91,93,44,34,109,97,120,70,101,101,80,101,114,66,108,111,98,71,97,115,34,58,110,117,108,108,125,44,34,111,117,116,34,58,110,117,108,108,125]} \ No newline at end of file diff --git a/contracts/verifier/snark_proof_with_public_inputs.json b/contracts/verifier/snark_proof_with_public_inputs.json index 85400eb2..68050c48 100644 --- a/contracts/verifier/snark_proof_with_public_inputs.json +++ b/contracts/verifier/snark_proof_with_public_inputs.json @@ -1 +1 @@ -{"Proof":{"Ar":{"X":"3223137300515445726621629654577034181236916187189785984102453772249712255827","Y":"2907185160819486517309582444046991589553988543708172017947532573798459447921"},"Krs":{"X":"7066186176465048809733280497216598020523106556044957581849945800840269416379","Y":"3732024050162698049865139506205846573121886992437414133229103952366510011770"},"Bs":{"X":{"A0":"3647581900857928744838950884624912135501405932076964650706778167110063289368","A1":"10872264759571928291757378913843731979794182183285532312639432495005516036045"},"Y":{"A0":"9235359712151784672496663847728441610467493809670596197164822332601059021360","A1":"8731929874657632816532791785050050105892306814781557898819317253682948163858"}},"Commitments":[{"X":"15835086452791747466946468947786652690521774906036198026832796976111003763868","Y":"6518905239803628186814550149282583795606243706243533259996248696440258609839"}],"CommitmentPok":{"X":"12811251794403685998689516148413985560091857813334005178016204587919771507178","Y":"9168106137408576766699902480770799271786919492461811035776871447094514990722"}},"PublicWitness":["6362267552962215457950634796317935612781553830779390456909670246098990432035","21220226220220531830097386689602577053359950660605734611847341805198693553528"]} \ No newline at end of file +{"Proof":{"Ar":{"X":"8728298070179409622671565494854414149764009252234770122552245295145748114760","Y":"13858057945550283848621204904214782713729779258955795681562397624675504543985"},"Krs":{"X":"20997660049140304173225637533332884179740846142089972818360000401204903854894","Y":"20753437672678271153299806809320762161121619327521260957221119302819973168817"},"Bs":{"X":{"A0":"3248938711780232333037827081553026435955782797126789609156631417061676001531","A1":"17503500096532406105577853167534849291027064713124894782037534009784190363382"},"Y":{"A0":"7651501675424767975396069876156119281192510645562446873886439818347912540845","A1":"1172973244327967912276078042774112866438916148782280438085955943730115670883"}},"Commitments":[{"X":"5560971376371596839091076966141222584791168032387407288654728348722054525189","Y":"11224943278815009758323907625780507294123965417950750137549104992567683189940"}],"CommitmentPok":{"X":"7613071802064773139672851697311193558206731447564551045030626068345706240434","Y":"17945904483608948640532351521618851519437605249090407298449250485970632473583"}},"PublicWitness":["5281439405489989899303957828569599236164595298153787119569151355395055400401","11970360391326087476580906000059380021614438020894280187376697902994770669641"]} \ No newline at end of file diff --git a/guest-program/README.md b/guest-program/README.md index 8030b3c5..2a66cbb8 100644 --- a/guest-program/README.md +++ b/guest-program/README.md @@ -4,12 +4,19 @@ ZKM can generate proof for Go and Rust (guest) Programs. * sha2-go -A simple program that takes struct Data as input, and operate the elements as an output. + A simple program that takes struct Data as input, and operates the elements as an output. * sha2-rust -It takes a public input and a private input ,then check the hash(private input)= public input. + + It takes a public input and a private input ,then checks the hash(private input)= public input. + +* mem-alloc-vec + + It allocs memories for vector ,then operates the memory(push and pop). -* mem-allox-vec +* revme + + This program is more complex, taking a block data as input and simulating the Ethereum Virtual Machine's computation for that block. > [!NOTE] > If you want to compile the guest programs, you should use a x86 Ubuntu22 machine with Rust: 1.81.0-nightly and Go : 1.22.1 @@ -43,5 +50,11 @@ cd zkm-project-template/guest-program/mem-alloc-vec cargo build --target=mips-unknown-linux-musl --release ``` -The compiled mips ELF is in the zkm-project-template/guest-program/revme/target/mips-unknown-linux-musl/release/ . +or +``` +cd zkm-project-template/guest-program/revme +cargo build --target=mips-unknown-linux-musl --release +``` + +The compiled mips ELF is in the zkm-project-template/guest-program/{sha2-rust,mem-alloc-vec,revme}/target/mips-unknown-linux-musl/release/ . diff --git a/host-program/run-local-proving.sh b/host-program/run-local-proving.sh index 0e64c25f..76ecb36a 100755 --- a/host-program/run-local-proving.sh +++ b/host-program/run-local-proving.sh @@ -13,6 +13,7 @@ export SEG_SIZE=262144 export ARGS="711e9609339e92b03ddc0a211827dba421f38f9ed8b9d806e1ffdd8c15ffa03d world!" export ELF_PATH=${BASEDIR}/../guest-program/$program/target/mips-unknown-linux-musl/release/$program export JSON_PATH=${BASEDIR}/test-vectors/test.json +export PROOF_RESULTS_PATH=${BASEDIR}/../contracts export EXECUTE_ONLY=false echo "Compile guest-program ${program}" diff --git a/host-program/run-network-proving.sh b/host-program/run-network-proving.sh index 7a9bb29a..d5eb469b 100755 --- a/host-program/run-network-proving.sh +++ b/host-program/run-network-proving.sh @@ -16,6 +16,7 @@ export SEG_SIZE=262144 export ARGS="711e9609339e92b03ddc0a211827dba421f38f9ed8b9d806e1ffdd8c15ffa03d world!" export ELF_PATH=${BASEDIR}/../guest-program/$program/target/mips-unknown-linux-musl/release/$program export JSON_PATH=${BASEDIR}/test-vectors/test.json +export PROOF_RESULTS_PATH=${BASEDIR}/../contracts export EXECUTE_ONLY=false echo "Compile guest-program ${program}" diff --git a/host-program/src/bin/zkm-prove.rs b/host-program/src/bin/zkm-prove.rs index 6a10a2aa..a4c6df66 100644 --- a/host-program/src/bin/zkm-prove.rs +++ b/host-program/src/bin/zkm-prove.rs @@ -1,13 +1,16 @@ use common::file; +//use hex; use serde::{Deserialize, Serialize}; +//use serde_json; +use serde_json::to_writer; use sha2::{Digest, Sha256}; use std::env; +use std::fs::read; +use std::fs::File; use std::path::Path; use std::time::Instant; use zkm_sdk::{prover::ProverInput, ProverClient}; -use std::fs::read; - #[tokio::main] async fn main() -> Result<(), Box> { env_logger::try_init().unwrap_or_default(); @@ -23,23 +26,28 @@ async fn main() -> Result<(), Box> { helper(); } - log::info!("new prover client."); - let prover_client = ProverClient::new().await; - log::info!("new prover client,ok."); - let seg_size = env::var("SEG_SIZE").unwrap_or("8192".to_string()); let seg_size2 = seg_size.parse::<_>().unwrap_or(65536); let execute_only = env::var("EXECUTE_ONLY").unwrap_or("false".to_string()); let execute_only2 = execute_only.parse::().unwrap_or(false); + let elf_path = env::var("ELF_PATH").expect("ELF PATH is missed"); + let args_parameter = env::var("ARGS").unwrap_or("data-to-hash".to_string()); + let json_path = env::var("JSON_PATH").expect("JSON PATH is missing"); + let proof_results_path = env::var("PROOF_RESULTS_PATH").unwrap_or("../contracts".to_string()); + + log::info!("new prover client."); + let prover_client = ProverClient::new().await; + log::info!("new prover client,ok."); let input: ProverInput = match args[1].as_str() { - "sha2-rust" => { - set_sha2_rust_input(seg_size2, execute_only2).expect("set sha2-rust input error") - } - "sha2-go" => set_sha2_go_input(seg_size2, execute_only2).expect("set sha2-go input error"), - "mem-alloc-vec" => set_mem_alloc_vec_input(seg_size2, execute_only2) + "sha2-rust" => set_sha2_rust_input(seg_size2, execute_only2, elf_path) + .expect("set sha2-rust input error"), + "sha2-go" => set_sha2_go_input(seg_size2, execute_only2, elf_path, args_parameter) + .expect("set sha2-go input error"), + "mem-alloc-vec" => set_mem_alloc_vec_input(seg_size2, execute_only2, elf_path) .expect("set mem-alloc-vec input error"), - "revme" => set_revme_input(seg_size2, execute_only2).expect("set revme input error"), + "revme" => set_revme_input(seg_size2, execute_only2, elf_path, json_path) + .expect("set revme input error"), _ => { helper(); ProverInput { @@ -65,7 +73,9 @@ async fn main() -> Result<(), Box> { ); return Err("SEG_SIZE is excessively large".into()); } - let output_dir = "../contracts/verifier".to_string(); + //1.snark proof + let output_dir = format!("{}/verifier", proof_results_path); + tokio::fs::create_dir_all(&output_dir).await?; let output_path = Path::new(&output_dir); let proof_result_path = output_path.join("snark_proof_with_public_inputs.json"); let mut f = file::new(&proof_result_path.to_string_lossy()); @@ -78,8 +88,36 @@ async fn main() -> Result<(), Box> { return Err("Proof: failed to write to file".into()); } } - //contract - let output_dir = "../contracts/src".to_string(); + + //2.handle the public inputs + let public_inputs = update_public_inputs_with_bincode( + input.public_inputstream, + &prover_result.public_values, + ); + match public_inputs { + Ok(Some(inputs)) => { + let output_dir = format!("{}/verifier", proof_results_path); + tokio::fs::create_dir_all(&output_dir).await?; + let output_path = Path::new(&output_dir); + let public_inputs_path = output_path.join("public_inputs.json"); + let mut fp = + File::create(public_inputs_path).expect("Unable to create file"); + //save the json file + to_writer(&mut fp, &inputs).expect("Unable to write to public input file"); + } + Ok(None) => { + log::info!("Failed to update the public inputs."); + return Err("Failed to update the public inputs.".into()); + } + Err(e) => { + log::info!("Failed to update the public inputs. error: {}", e); + return Err("Failed to update the public inputs.".into()); + } + } + + //3.contract + let output_dir = format!("{}/src", proof_results_path); + tokio::fs::create_dir_all(&output_dir).await?; let output_path = Path::new(&output_dir); let contract_path = output_path.join("verifier.sol"); let mut f = file::new(&contract_path.to_string_lossy()); @@ -92,7 +130,7 @@ async fn main() -> Result<(), Box> { return Err("Contract: failed to write to file".into()); } } - log::info!("Generating proof successfully .The proof file and verifier contract are in the the path contracts/verifier and contracts/src ."); + log::info!("Generating proof successfully .The proof file and verifier contract are in the the path {}/{{verifier,src}} .", proof_results_path); } else { match args[1].as_str() { "sha2-rust" => { @@ -144,21 +182,27 @@ async fn main() -> Result<(), Box> { Ok(()) } -fn set_sha2_rust_input(seg_size_u: u32, execute_only_b: bool) -> anyhow::Result { - let elf_path = env::var("ELF_PATH").expect("ELF PATH is missed"); - let num_bytes: usize = 1024; //Notice! : if this value is small, it will not generate the snark proof. +fn set_sha2_rust_input( + seg_size_u: u32, + execute_only_b: bool, + elf_path: String, +) -> anyhow::Result { + let num_bytes: usize = 1024; //Notice! : if this value is small, it will not generate the proof. let pri_input = vec![5u8; num_bytes]; let mut hasher = Sha256::new(); hasher.update(&pri_input); let result = hasher.finalize(); let output: [u8; 32] = result.into(); - // assume the arg[0] is the hash(input)(which is a public input), and the arg[1] is the input. + + // assume the arg[0] = hash(public input), and the arg[1] = public input. let public_input = output.to_vec(); let mut pub_buf = Vec::new(); bincode::serialize_into(&mut pub_buf, &public_input) .expect("public_input serialization failed"); + let mut pri_buf = Vec::new(); bincode::serialize_into(&mut pri_buf, &pri_input).expect("private_input serialization failed"); + let input = ProverInput { elf: read(elf_path).unwrap(), public_inputstream: pub_buf, @@ -167,7 +211,10 @@ fn set_sha2_rust_input(seg_size_u: u32, execute_only_b: bool) -> anyhow::Result< execute_only: execute_only_b, args: "".into(), }; - + log::info!( + "sha2_rust, bincode(pulic_input): {:?} ", + &input.public_inputstream + ); Ok(input) } @@ -220,9 +267,12 @@ impl Data { } } -fn set_sha2_go_input(seg_size_u: u32, execute_only_b: bool) -> anyhow::Result { - let elf_path = env::var("ELF_PATH").expect("ELF PATH is missed"); - let args = env::var("ARGS").unwrap_or("data-to-hash".to_string()); +fn set_sha2_go_input( + seg_size_u: u32, + execute_only_b: bool, + elf_path: String, + args: String, +) -> anyhow::Result { // assume the arg[0] is the hash(input)(which is a public input), and the arg[1] is the input. let args: Vec<&str> = args.split_whitespace().collect(); assert_eq!(args.len(), 2); @@ -235,40 +285,100 @@ fn set_sha2_go_input(seg_size_u: u32, execute_only_b: bool) -> anyhow::Result anyhow::Result { - let elf_path = env::var("ELF_PATH").expect("ELF PATH is missed"); +fn set_mem_alloc_vec_input( + seg_size_u: u32, + execute_only_b: bool, + elf_path: String, +) -> anyhow::Result { let input = ProverInput { elf: read(elf_path).unwrap(), - public_inputstream: "".into(), - private_inputstream: "".into(), + public_inputstream: "".into(), //the public input is empty + private_inputstream: "".into(), //the private input is empty seg_size: seg_size_u, execute_only: execute_only_b, args: "".into(), }; - + log::info!( + "set_mem_alloc_vec_input, bincode(pulic_input): {:?} ", + &input.public_inputstream + ); Ok(input) } -fn set_revme_input(seg_size_u: u32, execute_only_b: bool) -> anyhow::Result { - let elf_path = env::var("ELF_PATH").expect("ELF PATH is missed"); - let json_path = env::var("JSON_PATH").expect("JSON PATH is missing"); +fn set_revme_input( + seg_size_u: u32, + execute_only_b: bool, + elf_path: String, + json_path: String, +) -> anyhow::Result { let input = ProverInput { elf: read(elf_path).unwrap(), public_inputstream: read(json_path).unwrap(), - private_inputstream: "".into(), + private_inputstream: "".into(), //the private input is empty seg_size: seg_size_u, execute_only: execute_only_b, args: "".into(), }; - + log::info!( + "revme, bincode(pulic_input): {:?} ", + &input.public_inputstream + ); Ok(input) } + +#[derive(Serialize, Deserialize, Debug)] +struct PublicInputs { + roots_before: Roots, + roots_after: Roots, + userdata: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +struct Roots { + root: Vec, +} + +fn update_public_inputs_with_bincode( + public_inputstream: Vec, + proof_public_inputs: &[u8], +) -> anyhow::Result> { + let mut hasher = Sha256::new(); + hasher.update(&public_inputstream); + let result_hs = hasher.finalize(); + let output_hs: [u8; 32] = result_hs.into(); + + let slice_bt: &[u8] = proof_public_inputs; + let mut public_inputs: PublicInputs = + serde_json::from_slice(slice_bt).expect("Failed to parse JSON"); + + //1.check the userdata (from the proof) = hash(bincode(host's public_inputs)) ? + let userdata = public_inputs.userdata; + if userdata == output_hs { + log::info!(" hash(bincode(pulic_input)): {:?} ", &output_hs); + } else { + log::info!( + "public inputs's hash is different. the proof's is: {:?}, host's is :{:?} ", + userdata, + output_hs + ); + return Err(anyhow::anyhow!( + "Public inputs's hash does not match the proof's userdata." + )); + } + + //2, update userdata with bincode(host's public_inputs). + public_inputs.userdata = public_inputstream; + Ok(Some(public_inputs)) +} diff --git a/sdk/README.md b/sdk/README.md new file mode 100644 index 00000000..492fc019 --- /dev/null +++ b/sdk/README.md @@ -0,0 +1,37 @@ +# ZKM SDK usage + +## Use the libsnark + +1. The compile.sh in the path sdk/src/local/libsnark only supports X86_64 linux.For MacOS, there is a [Dockerfile](../Dockerfile) in the template. + +``` +cd zkm-project-template/sdk/src/local/libsnark +./compile.sh +``` + If successful, it will generate the libsnark.so in sdk/src/local/libsnark/ + +2. To instruct your Rust environment on the location of the libsnark.so , you can set the LD_LIBRARY_PATH environment variable. For example: + +``` +export LD_LIBRARY_PATH=Your BASEDIR/zkm-project-template/sdk/src/local/libsnark:$LD_LIBRARY_PATH +``` + +3. Import the SDK + +``` +// Cargo.toml +[dependencies] +zkm-sdk = { git = "https://github.com/zkMIPS/zkm-project-template", branch = "main", features = ["snark"] } +``` + +## Don't use the libsnark + +1. Set the environment variable `NO_USE_SNARK=true` . + +2. Import the SDK + +``` +// Cargo.toml +[dependencies] +zkm-sdk = { git = "https://github.com/zkMIPS/zkm-project-template", branch = "main" } +``` diff --git a/sdk/src/local/libsnark/contract.go b/sdk/src/local/libsnark/contract.go index 355664e4..2bdb6014 100644 --- a/sdk/src/local/libsnark/contract.go +++ b/sdk/src/local/libsnark/contract.go @@ -216,15 +216,13 @@ contract Verifier { } - function verifyUserData( - uint8[32] memory _userData, + function calculatePublicInput( + bytes 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)); - } + bytes32 userData = sha256(_userData); + uint256 memRootBefore = 0; for (uint256 i = 0; i < 8; i++) { memRootBefore |= uint256(_memRootBefore[i]) << (32 * (7 - i)); diff --git a/sdk/src/local/stark.rs b/sdk/src/local/stark.rs index 8cc41c87..d3532563 100644 --- a/sdk/src/local/stark.rs +++ b/sdk/src/local/stark.rs @@ -13,14 +13,9 @@ pub fn prove_stark( let seg_size = input.seg_size as usize; let file = ElfBytes::::minimal_parse(input.elf.as_slice()) .expect("opening elf file failed"); - let mut args: Vec<&str> = input.args.split_whitespace().collect(); - if args.len() > 2 { - args.truncate(2); - } - log::info!("args: {:?}", args); let mut state = State::load_elf(&file); state.patch_elf(&file); - state.patch_stack(args); + state.patch_stack(vec![]); state.input_stream.push(input.public_inputstream.clone()); state.input_stream.push(input.private_inputstream.clone()); diff --git a/sdk/src/local/util.rs b/sdk/src/local/util.rs index 6d6e24cb..cc74edab 100644 --- a/sdk/src/local/util.rs +++ b/sdk/src/local/util.rs @@ -217,13 +217,12 @@ pub fn prove_multi_seg_common( let wrapped_proof = wrapped_circuit.prove(&block_proof)?; wrapped_proof.save(outdir)?; - let outdir_path = std::path::Path::new(outdir); - 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 outdir_path = std::path::Path::new(outdir); + 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_file = File::create(outdir_path.join("block_public_inputs.json"))?; serde_json::to_writer(&block_public_inputs_file, &block_public_inputs)?;