UNPKG

o1js

Version:

TypeScript framework for zk-SNARKs and zkApps

95 lines (76 loc) 2.51 kB
/** * This example deploys a zkApp and then updates its verification key via proof, self-replacing the zkApp */ import { SmartContract, VerificationKey, method, Permissions, Mina, AccountUpdate, Provable, } from 'o1js'; class SelfUpdater extends SmartContract { init() { super.init(); this.account.permissions.set({ ...Permissions.default(), setVerificationKey: Permissions.VerificationKey.proofDuringCurrentVersion(), }); } @method async replaceVerificationKey(verificationKey: VerificationKey) { this.account.verificationKey.set(verificationKey); } } class Bar extends SmartContract { @method async call() { Provable.log('Bar'); } } // setup const Local = await Mina.LocalBlockchain({ proofsEnabled: true }); Mina.setActiveInstance(Local); const contractAccount = Mina.TestPublicKey.random(); const contract = new SelfUpdater(contractAccount); const [deployer] = Local.testAccounts; // deploy first verification key await SelfUpdater.compile(); const tx = await Mina.transaction(deployer, async () => { AccountUpdate.fundNewAccount(deployer); await contract.deploy(); }); await tx.prove(); await tx.sign([deployer.key, contractAccount.key]).send(); const fooVerificationKey = Mina.getAccount(contractAccount).zkapp?.verificationKey; Provable.log('original verification key', fooVerificationKey); // update verification key const { verificationKey: barVerificationKey } = await Bar.compile(); try { const invalidVerificationKey = new VerificationKey({ data: fooVerificationKey!.data, hash: barVerificationKey.hash, }); const tx2x = await Mina.transaction(deployer, async () => { // VK with mismatched hash and data should throw await contract.replaceVerificationKey(invalidVerificationKey); }); await tx2x.prove(); await tx2x.sign([deployer.key]).send(); } catch (error: any) { if ( error.message.includes('The verification key hash is not consistent with the provided data') ) { console.log('correctly threw on invalid verification key'); } else { throw error; } } const tx2 = await Mina.transaction(deployer, async () => { // This call will work because the vk is valid await contract.replaceVerificationKey(barVerificationKey); }); await tx2.prove(); await tx2.sign([deployer.key]).send(); const updatedVerificationKey = Mina.getAccount(contractAccount).zkapp?.verificationKey; // should be different from Foo Provable.log('updated verification key', updatedVerificationKey);