diff --git a/contracts/src/Sxg.sol b/contracts/src/Sxg.sol index 285ce83..b4529ca 100644 --- a/contracts/src/Sxg.sol +++ b/contracts/src/Sxg.sol @@ -1,16 +1,36 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {ISP1Verifier} from "@sp1-contracts/ISP1Verifier.sol"; +/// @title SP1 Verifier Interface +/// @author Succinct Labs +/// @notice This contract is the interface for the SP1 Verifier. +interface ISP1Verifier { + /// @notice Verifies a proof with given public values and vkey. + /// @dev It is expected that the first 4 bytes of proofBytes must match the first 4 bytes of + /// target verifier's VERIFIER_HASH. + /// @param programVKey The verification key for the RISC-V program. + /// @param publicValues The public values encoded as bytes. + /// @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes. + function verifyProof( + bytes32 programVKey, + bytes calldata publicValues, + bytes calldata proofBytes + ) external view; +} + +interface ISP1VerifierWithHash is ISP1Verifier { + /// @notice Returns the hash of the verifier. + function VERIFIER_HASH() external pure returns (bytes32); +} struct PublicValuesStruct { uint32 result; + uint8[] data_to_verify; } /// @title Sxg. -/// @author Succinct Labs -/// @notice This contract implements a simple example of verifying the proof of a computing a -/// fibonacci number. +/// @author Crema Labs +/// @notice This contract implements a simple example of verifying the proof sxg. contract SXG { /// @notice The address of the SP1 verifier contract. /// @dev This can either be a specific SP1Verifier for a specific version, or the @@ -30,10 +50,11 @@ contract SXG { /// @notice The entrypoint for verifying the proof of a sxg number. /// @param _proofBytes The encoded proof. /// @param _publicValues The encoded public values. + function verifySXGProof( bytes calldata _publicValues, bytes calldata _proofBytes - ) public view returns (uint32) { + ) public view returns (uint32, string memory) { ISP1Verifier(verifier).verifyProof( sxgProgramVKey, _publicValues, @@ -44,6 +65,24 @@ contract SXG { (PublicValuesStruct) ); - return publicValues.result; + string memory data_to_verify_str = convertToASCII( + publicValues.data_to_verify + ); + + return (publicValues.result, data_to_verify_str); + } + + function convertToASCII( + uint8[] memory data + ) internal pure returns (string memory) { + bytes memory asciiBytes = new bytes(data.length); + for (uint i = 0; i < data.length; i++) { + require( + data[i] >= 32 && data[i] <= 126, + "Input contains non-printable ASCII characters" + ); + asciiBytes[i] = bytes1(data[i]); + } + return string(asciiBytes); } } diff --git a/contracts/src/fixtures/groth16-fixture.json b/contracts/src/fixtures/groth16-fixture.json index a289385..bfde58a 100644 --- a/contracts/src/fixtures/groth16-fixture.json +++ b/contracts/src/fixtures/groth16-fixture.json @@ -1,6 +1,6 @@ { "result": 1, - "vkey": "0x00cacd7a6bd9bf05403e6025a3f07687589f397c117db0387631fc2acb105eff", - "publicValues": "0x0000000000000000000000000000000000000000000000000000000000000001", - "proof": "0x6a2906ac21d04f16a0b65a4614269ffaa702b89e5f4af256bf057d7210ea14d2e4eb003718416563bd7c3558910f61a515ec26b3aaba426931da7e0196e1c007827c4bda2947aa3e01c50b0d09205a076be5f96f3093d081e8ddfe0ed20d5bdbeeae3080240a293565baa15ef6787722810f6d70411f920f054e22a3a94a92e5f3cfc90d1bec7415f91ecf1ee6493c6e8d2736059afeda7c4e1b5a6f11c61cd5936db86e0d27d53150eb1a1137044994767c44dc5d61a65c76f95a9fd416e35de1b6982b2a407fc15fa38cf2df4f64fc6f3eb84a7f6e73a6cc01b3916db1734f3e8698b90b62224a46f50fae2d637b0dd7e7d70854bb87e99d6426cc58132c8b98563f42" + "vkey": "0x00a0e618e71b21b9a573b86f463534b87b469655a024665b54ec256f6831446d", + "publicValues": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006200000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000007500000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000020", + "proof": "0x6a2906ac21ce0f452cf45bc66dc4c788318602dded2efd89566ef4340aa31ed7c62ea63724a46efa300b4209e95b1e7343838cf75bc8be3ae97953c8083ebc95092a5b612cfeebdbf87105d3950cd585a9088717f48d79d852e4543d492d634054394c0b245c3020d5695f563e3da5adc1b05967633f8d6a3c730088a0d9f225fc5dc5921fe4d54eb4e142effd5c1ac44af8774e342ca2a410e77b7635dc092c6bc1ead30188c96c94d2976a95ab289b5ac827aad8f1380f664ed7c1243a51ffe015941121546239e317c37364bd5c50fa6169f6145ae3572737831ab1caa117a9d40c08105a1b0df1cf71d3a56eb6ca29b256480d390a89348c9daeb841d02dd7f228d9" } \ No newline at end of file diff --git a/contracts/test/Sxg.t.sol b/contracts/test/Sxg.t.sol index 95db748..be72167 100644 --- a/contracts/test/Sxg.t.sol +++ b/contracts/test/Sxg.t.sol @@ -21,14 +21,15 @@ contract SXGTest is Test { return SP1ProofFixtureJson({ result: 1, - vkey: 0x00cacd7a6bd9bf05403e6025a3f07687589f397c117db0387631fc2acb105eff, - publicValues: hex"0000000000000000000000000000000000000000000000000000000000000001", - proof: hex"6a2906ac21d04f16a0b65a4614269ffaa702b89e5f4af256bf057d7210ea14d2e4eb003718416563bd7c3558910f61a515ec26b3aaba426931da7e0196e1c007827c4bda2947aa3e01c50b0d09205a076be5f96f3093d081e8ddfe0ed20d5bdbeeae3080240a293565baa15ef6787722810f6d70411f920f054e22a3a94a92e5f3cfc90d1bec7415f91ecf1ee6493c6e8d2736059afeda7c4e1b5a6f11c61cd5936db86e0d27d53150eb1a1137044994767c44dc5d61a65c76f95a9fd416e35de1b6982b2a407fc15fa38cf2df4f64fc6f3eb84a7f6e73a6cc01b3916db1734f3e8698b90b62224a46f50fae2d637b0dd7e7d70854bb87e99d6426cc58132c8b98563f42" + vkey: 0x00a0e618e71b21b9a573b86f463534b87b469655a024665b54ec256f6831446d, + publicValues: hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006200000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000007500000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000020", + proof: hex"6a2906ac21ce0f452cf45bc66dc4c788318602dded2efd89566ef4340aa31ed7c62ea63724a46efa300b4209e95b1e7343838cf75bc8be3ae97953c8083ebc95092a5b612cfeebdbf87105d3950cd585a9088717f48d79d852e4543d492d634054394c0b245c3020d5695f563e3da5adc1b05967633f8d6a3c730088a0d9f225fc5dc5921fe4d54eb4e142effd5c1ac44af8774e342ca2a410e77b7635dc092c6bc1ead30188c96c94d2976a95ab289b5ac827aad8f1380f664ed7c1243a51ffe015941121546239e317c37364bd5c50fa6169f6145ae3572737831ab1caa117a9d40c08105a1b0df1cf71d3a56eb6ca29b256480d390a89348c9daeb841d02dd7f228d9" }); } function setUp() public { SP1ProofFixtureJson memory fixture = loadSample(); + verifier = address(new SP1VerifierGateway(address(1))); sxg = new SXG(verifier, fixture.vkey); @@ -41,7 +42,13 @@ contract SXGTest is Test { abi.encodeWithSelector(SP1VerifierGateway.verifyProof.selector), abi.encode(true) ); - uint32 result = sxg.verifySXGProof(fixture.publicValues, fixture.proof); + + (uint32 result, string memory data_to_verify) = sxg.verifySXGProof( + fixture.publicValues, + fixture.proof + ); + + console.log(data_to_verify); assert(result == 1); } @@ -50,7 +57,11 @@ contract SXGTest is Test { bytes memory fakeProof = new bytes(fixture.proof.length); - uint32 result = sxg.verifySXGProof(fixture.publicValues, fakeProof); + (uint32 result, string memory sui) = sxg.verifySXGProof( + fixture.publicValues, + fixture.proof + ); + console.log(sui); assert(result == 0); } } diff --git a/elf/riscv32im-succinct-zkvm-elf b/elf/riscv32im-succinct-zkvm-elf index 751e4bf..fcd4c63 100755 Binary files a/elf/riscv32im-succinct-zkvm-elf and b/elf/riscv32im-succinct-zkvm-elf differ diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 43bced3..8e3b86a 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -10,6 +10,7 @@ sol! { /// The public values encoded as a struct that can be easily deserialized inside Solidity. struct PublicValuesStruct { uint32 result; + uint8[] data_to_verify; } } diff --git a/program/src/main.rs b/program/src/main.rs index 68fc271..e3168ca 100644 --- a/program/src/main.rs +++ b/program/src/main.rs @@ -8,6 +8,11 @@ use lib::PublicValuesStruct; pub fn main() { let sxg_input = sp1_zkvm::io::read::(); let result = sxg_input.verify().unwrap() as u32; - let bytes = PublicValuesStruct::abi_encode(&PublicValuesStruct { result }); + + let bytes = PublicValuesStruct::abi_encode(&PublicValuesStruct { + result, + data_to_verify: sxg_input.data_to_verify, + }); + sp1_zkvm::io::commit_slice(&bytes); } diff --git a/script/src/bin/evm.rs b/script/src/bin/evm.rs index d3c1212..ee70eae 100644 --- a/script/src/bin/evm.rs +++ b/script/src/bin/evm.rs @@ -65,6 +65,7 @@ fn main() { let mut stdin = SP1Stdin::new(); let input_file = format!("{}.json", args.input_file_id); + let file_content = fs::read_to_string(input_file).unwrap(); let sxg_input: SXGInput = serde_json::from_str(&file_content).unwrap(); @@ -91,7 +92,10 @@ fn create_proof_fixture( ) { // Deserialize the public values. let bytes = proof.public_values.as_slice(); - let PublicValuesStruct { result } = PublicValuesStruct::abi_decode(bytes, false).unwrap(); + let PublicValuesStruct { + result, + data_to_verify, + } = PublicValuesStruct::abi_decode(bytes, false).unwrap(); // Create the testing fixture so we can test things end-to-end. let fixture = SP1SXGProofFixture { @@ -103,6 +107,9 @@ fn create_proof_fixture( println!("Result: {}", fixture.result); + let data_to_verify_str = String::from_utf8(data_to_verify).unwrap(); + println!("Data Verified: {:?}", data_to_verify_str); + // The verification key is used to verify that the proof corresponds to the execution of the // program on the given input. // diff --git a/script/src/bin/main.rs b/script/src/bin/main.rs index e62cdf3..3b56373 100644 --- a/script/src/bin/main.rs +++ b/script/src/bin/main.rs @@ -58,9 +58,15 @@ fn main() { println!("Program executed successfully."); let decoded = PublicValuesStruct::abi_decode(output.as_slice(), true).unwrap(); - let PublicValuesStruct { result } = decoded; + let PublicValuesStruct { + result, + data_to_verify, + } = decoded; println!("SXG verification result: {}", result); + let data_to_verify_str = String::from_utf8(data_to_verify).unwrap(); + println!("Data Verified: {:?}", data_to_verify_str); + assert_eq!(result, 1); println!("SXG verification is successful!");