UNPKG

@nori-zk/ethprocessor

Version:

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

99 lines 4.18 kB
import { AccountUpdate, Mina, PrivateKey, Cache, UInt64, } from 'o1js'; import { EthProcessor } from './EthProcessor.js'; import { EthVerifier, EthInput, Bytes32 } from './EthVerifier.js'; import fs from 'fs'; import { NodeProofLeft } from '@nori-zk/proof-conversion'; import { ethers } from 'ethers'; import { PATH_TO_O1_PROOF, PATH_TO_SP1_PROOF } from './proofs.js'; // Configuration const proofsEnabled = true; // Contract state variables let deployerAccount; let deployerKey; let senderAccount; let senderKey; let zkAppAddress; let zkAppPrivateKey; let zkApp; let vk; async function main() { try { // Compile and setup vk = (await EthVerifier.compile({ cache: Cache.FileSystemDefault })) .verificationKey; if (proofsEnabled) { await EthProcessor.compile(); } // const ethV = await EthVerifier.analyzeMethods(); // console.log('ethV', ethV.compute.summary()); // const ethP = await EthProcessor.analyzeMethods(); // console.log('ethP', ethP); // Initialize local blockchain const Local = await Mina.LocalBlockchain({ proofsEnabled }); Mina.setActiveInstance(Local); [deployerAccount, senderAccount] = Local.testAccounts; deployerKey = deployerAccount.key; senderKey = senderAccount.key; // Deploy contract zkAppPrivateKey = PrivateKey.random(); zkAppAddress = zkAppPrivateKey.toPublicKey(); zkApp = new EthProcessor(zkAppAddress); const deployTx = await Mina.transaction(deployerAccount, async () => { AccountUpdate.fundNewAccount(deployerAccount); await zkApp.deploy(); }); await deployTx.prove(); await deployTx.sign([deployerKey, zkAppPrivateKey]).send(); console.log('Successfully deployed EthProcessor'); // Process proof data const rawProof = await NodeProofLeft.fromJSON(JSON.parse(fs.readFileSync(PATH_TO_O1_PROOF, 'utf8'))); const ethSP1Proof = JSON.parse(fs.readFileSync(PATH_TO_SP1_PROOF, 'utf8')); // JK FIXME why is the proof coming from example file // Decode proof values const defaultEncoder = ethers.AbiCoder.defaultAbiCoder(); // JK factorise deecoders const decoded = defaultEncoder.decode([ 'bytes32', 'bytes32', 'bytes32', 'uint64', 'bytes32', 'uint64', 'bytes32', 'bytes32', ], new Uint8Array(Buffer.from(ethSP1Proof.public_values.buffer.data))); // Create input for verification const input = new EthInput({ executionStateRoot: Bytes32.fromHex(decoded[0].slice(2)), newHeader: Bytes32.fromHex(decoded[1].slice(2)), nextSyncCommitteeHash: Bytes32.fromHex(decoded[2].slice(2)), newHead: UInt64.from(decoded[3]), prevHeader: Bytes32.fromHex(decoded[4].slice(2)), prevHead: UInt64.from(decoded[5]), syncCommitteeHash: Bytes32.fromHex(decoded[6].slice(2)), startSyncComitteHash: Bytes32.fromHex(decoded[7].slice(2)), }); // Compute and verify proof console.log('Computing proof...'); const proof = await EthVerifier.compute(input, rawProof); // Update contract state console.log('Creating update transaction...'); const updateTx = await Mina.transaction(senderAccount, async () => { await zkApp.update(proof.proof); }); await updateTx.prove(); await updateTx.sign([senderKey]).send(); // Verify updated state const updatedState = Mina.getAccount(zkAppAddress); const updatedHeadState = zkApp.latestHead.get(); console.log('Updated latestHead:', updatedState.zkapp?.appState[1].toString()); console.log('Updated head state:', updatedHeadState.toString()); // const events = await zkApp.fetchEvents(); // console.log(events[0].event.data); } catch (error) { console.error('Error:', error); process.exit(1); } } main().catch(console.error); //# sourceMappingURL=EthScript.js.map