UNPKG

@nori-zk/ethprocessor

Version:

zkApp for verifying SP1 Helios Nori proof and storing latest execution state root on Mina

87 lines 6.73 kB
import { Provable, VerificationKey, Poseidon, UInt8, Bytes, ZkProgram, Struct, UInt64, Field, } from 'o1js'; import { FrC, NodeProofLeft, parsePlonkPublicInputsProvable, wordToBytes, } from '@nori-zk/proof-conversion'; class Bytes32 extends Bytes(32) { } // sol! { // struct ProofOutputs { // bytes32 executionStateRoot; // bytes32 newHeader; // bytes32 nextSyncCommitteeHash; // uint256 newHead; // bytes32 prevHeader; // uint256 prevHead; // bytes32 syncCommitteeHash; // } // } class EthInput extends Struct({ executionStateRoot: Bytes32.provable, newHeader: Bytes32.provable, nextSyncCommitteeHash: Bytes32.provable, newHead: UInt64, prevHeader: Bytes32.provable, prevHead: UInt64, syncCommitteeHash: Bytes32.provable, startSyncComitteHash: Bytes32.provable, }) { } const EthVerifier = ZkProgram({ name: 'EthVerifier', publicInput: EthInput, publicOutput: Field, methods: { compute: { privateInputs: [NodeProofLeft], async method(input, proof) { // if (process.env.BLOBSTREAM_ENABLED == 'true') { // ethProgramVK = FrC.from(process.env.BLOBSTREAM_PROGRAM_VK as string); // These should be the same // JK to swap in CI after contract gets updated and redeployed const ethPlonkVK = FrC.from('356461990772566150229371218896390328991028774865907497243179150670146300968' //$programVK todo check ? ); // p0 = ConverterInputMessage.proofConversionOutput.proofData.publicOutput[2] const ethNodeVk = Field.from('28260390150731392236641024269553678227550500922769773705331708504563351523466'); // Verification of proof conversion // vk = ConverterInputMessage.proofConversionOutput.vkData const vk = VerificationKey.fromJSON(JSON.parse(`{"data":"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","hash":"16513322678631837892015513717531806224957815970230988593763371397739021076098"}`) //to be hardcoded ); // Above hardcoded, as long as SP1 logi unchanged // Updates with SP1 updates // [zkProgram / circuit][eth processor / contract ie on-chain state] proof.verify(vk); // Passed proof matches extracted public entry 2 proof.publicOutput.subtreeVkDigest.assertEquals(ethNodeVk); // Provable.log('all', input); // Provable.log('newHeader', input.newHeader); Provable.log('newHead slot', input.newHead); // Verification of the input let bytes = []; bytes = bytes.concat(input.executionStateRoot.bytes); bytes = bytes.concat(input.newHeader.bytes); bytes = bytes.concat(input.nextSyncCommitteeHash.bytes); bytes = bytes.concat(padUInt64To32Bytes(input.newHead)); bytes = bytes.concat(input.prevHeader.bytes); bytes = bytes.concat(padUInt64To32Bytes(input.prevHead)); bytes = bytes.concat(input.syncCommitteeHash.bytes); bytes = bytes.concat(input.startSyncComitteHash.bytes); // bytes = bytes.concat(uint64ToBytes32(input.prevHead)); // bytes = bytes.concat(uint64ToBytes32(input.newHead)); // Check that zkporgraminput is same as passed to the SP1 program const pi0 = ethPlonkVK; const pi1 = parsePlonkPublicInputsProvable(Bytes.from(bytes)); const piDigest = Poseidon.hashPacked(Provable.Array(FrC.provable, 2), [pi0, pi1]); Provable.log('piDigest', piDigest); Provable.log('proof.publicOutput.rightOut', proof.publicOutput.rightOut); piDigest.assertEquals(proof.publicOutput.rightOut); return { publicOutput: new Field(1) }; }, }, }, }); const EthProof = ZkProgram.Proof(EthVerifier); export { EthVerifier, EthProof, EthInput, Bytes32 }; const padUInt64To32Bytes = (num) => { let unpadded = []; unpadded = wordToBytes(num.toFields()[0]); return [...unpadded, ...Array(24).fill(UInt8.from(0))].reverse(); }; //# sourceMappingURL=EthVerifier.js.map