@nori-zk/ethprocessor
Version:
zkApp for verifying SP1 Helios Nori proof and storing latest execution state root on Mina
197 lines • 12.3 kB
JavaScript
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _MinaEthProcessorSubmitter_instances, _MinaEthProcessorSubmitter_zkApp, _MinaEthProcessorSubmitter_senderPrivateKey, _MinaEthProcessorSubmitter_zkAppPrivateKey, _MinaEthProcessorSubmitter_network, _MinaEthProcessorSubmitter_txFee, _MinaEthProcessorSubmitter_testMode, _MinaEthProcessorSubmitter_ethProcessorVerificationKey_get, _MinaEthProcessorSubmitter_ethVerifierVerificationKey_get;
import 'dotenv/config';
import { AccountUpdate, Mina, PrivateKey, fetchAccount } from 'o1js';
import { Logger } from 'esm-iso-logger';
import { EthProcessor } from './ethProcessor.js';
import { EthVerifier, EthInput, ethVerifierVkHash, decodeConsensusMptProof, Bytes32FieldPair, NodeProofLeft, compileAndOptionallyVerifyContracts, } from '@nori-zk/o1js-zk-utils';
import { cacheFactory } from '@nori-zk/o1js-zk-utils/node';
import { ethProcessorVkHash } from './integrity/EthProcessor.VKHash.js';
const logger = new Logger('EthProcessorSubmitter');
export class MinaEthProcessorSubmitter {
constructor(cache = undefined) {
_MinaEthProcessorSubmitter_instances.add(this);
this.cache = cache;
_MinaEthProcessorSubmitter_zkApp.set(this, void 0);
_MinaEthProcessorSubmitter_senderPrivateKey.set(this, void 0);
_MinaEthProcessorSubmitter_zkAppPrivateKey.set(this, void 0);
_MinaEthProcessorSubmitter_network.set(this, void 0);
_MinaEthProcessorSubmitter_txFee.set(this, void 0);
_MinaEthProcessorSubmitter_testMode.set(this, void 0);
void __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_instances, "a", _MinaEthProcessorSubmitter_ethVerifierVerificationKey_get);
void __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_testMode, "f");
logger.info(`🛠 MinaEthProcessorSubmitter constructor called!`);
const errors = [];
const senderPrivateKeyBase58 = process.env.SENDER_PRIVATE_KEY;
const network = process.env.NETWORK;
const zkAppPrivateKeyBase58 = process.env.ZKAPP_PRIVATE_KEY;
const networkUrl = process.env.MINA_RPC_NETWORK_URL;
if (!senderPrivateKeyBase58)
errors.push('SENDER_PRIVATE_KEY is required');
if (!network) {
errors.push('NETWORK is required');
}
else if (!['devnet', 'mainnet', 'lightnet'].includes(network)) {
errors.push(`NETWORK must be one of: devnet, mainnet, lightnet (got "${network}")`);
}
else {
__classPrivateFieldSet(this, _MinaEthProcessorSubmitter_network, network, "f");
}
if (!networkUrl) {
errors.push('MINA_RPC_NETWORK_URL is required');
}
if (!zkAppPrivateKeyBase58) {
errors.push('ZKAPP_PRIVATE_KEY is required when not in lightnet mode');
}
if (errors.length > 0) {
throw `Configuration errors:\n- ${errors.join('\n- ')}`;
}
__classPrivateFieldSet(this, _MinaEthProcessorSubmitter_senderPrivateKey, PrivateKey.fromBase58(senderPrivateKeyBase58), "f");
__classPrivateFieldSet(this, _MinaEthProcessorSubmitter_zkAppPrivateKey, PrivateKey.fromBase58(zkAppPrivateKeyBase58), "f");
__classPrivateFieldSet(this, _MinaEthProcessorSubmitter_zkApp, new EthProcessor(__classPrivateFieldGet(this, _MinaEthProcessorSubmitter_zkAppPrivateKey, "f").toPublicKey()), "f");
__classPrivateFieldSet(this, _MinaEthProcessorSubmitter_txFee, Number(process.env.TX_FEE || 0.1) * 1e9, "f");
__classPrivateFieldSet(this, _MinaEthProcessorSubmitter_testMode, process.env.NETWORK === 'lightnet', "f");
this.minaRPCNetworkUrl = networkUrl;
logger.log('Loaded constants from: .env');
}
async networkSetUp() {
logger.log(`Setting up ${__classPrivateFieldGet(this, _MinaEthProcessorSubmitter_network, "f")} network with RPC endpoint: '${this.minaRPCNetworkUrl}'.`);
const networkId = __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_network, "f") === 'mainnet' ? 'mainnet' : 'testnet';
const Network = Mina.Network({
networkId,
mina: this.minaRPCNetworkUrl,
});
Mina.setActiveInstance(Network);
logger.log('Finished Mina network setup.');
}
async compileContracts() {
const fileSystemCache = this.cache
? await cacheFactory(this.cache)
: undefined;
logger.log('fileSystemCache', fileSystemCache, this.cache);
const { ethVerifierVerificationKey, ethProcessorVerificationKey } = await compileAndOptionallyVerifyContracts(logger, [
{
name: 'ethVerifier',
program: EthVerifier,
integrityHash: ethVerifierVkHash,
},
{
name: 'ethProcessor',
program: EthProcessor,
integrityHash: ethProcessorVkHash,
},
], fileSystemCache);
Object.defineProperty(this, 'ethVerifierVerificationKey', {
value: ethVerifierVerificationKey,
writable: false,
configurable: false,
enumerable: true,
});
Object.defineProperty(this, 'ethProcessorVerificationKey', {
value: ethProcessorVerificationKey,
writable: false,
configurable: false,
enumerable: true,
});
}
async deployContract(storeHash) {
if (__classPrivateFieldGet(this, _MinaEthProcessorSubmitter_network, "f") !== 'lightnet') {
throw new Error([
//prettier-ignore
`Deploy is only supported in test mode, test mode was set to 'false'. Test mode is only possible when the configured network is 'lightnet' and the configured network is '${__classPrivateFieldGet(this, _MinaEthProcessorSubmitter_network, "f")}'.`,
`Please see the README.md within the 'contracts/mina/eth-processor' workspace of the 'nori-bridge-sdk' repository and use the deploy script 'npm run deploy <storeHash>' instead of this method.`,
].join('\n'));
}
logger.log('Creating deploy update transaction.');
const senderPublicKey = __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_senderPrivateKey, "f").toPublicKey();
const deployTx = await Mina.transaction({ sender: senderPublicKey, fee: __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_txFee, "f") }, async () => {
AccountUpdate.fundNewAccount(senderPublicKey);
logger.log(`Deploying smart contract with verification key hash: '${__classPrivateFieldGet(this, _MinaEthProcessorSubmitter_instances, "a", _MinaEthProcessorSubmitter_ethProcessorVerificationKey_get).hash}'`);
await __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_zkApp, "f").deploy({
verificationKey: __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_instances, "a", _MinaEthProcessorSubmitter_ethProcessorVerificationKey_get),
});
logger.log(`Initializing with adminPublicKey '${senderPublicKey.toBase58()}' and store hash '${storeHash.toHex()}'.`);
await __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_zkApp, "f").initialize(senderPublicKey, Bytes32FieldPair.fromBytes32(storeHash));
});
logger.log('Deploy transaction created successfully. Proving...');
await deployTx.prove();
logger.log('Transaction proved. Signing and sending the transaction...');
await deployTx
.sign([__classPrivateFieldGet(this, _MinaEthProcessorSubmitter_senderPrivateKey, "f"), __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_zkAppPrivateKey, "f")])
.send()
.wait();
logger.log('EthProcessor deployed successfully.');
}
async createProof(proofArguments) {
try {
logger.log('Creating proof.');
const { sp1PlonkProof, conversionOutputProof } = proofArguments;
const rawProof = await NodeProofLeft.fromJSON(conversionOutputProof.proofData);
const ethSP1Proof = sp1PlonkProof;
logger.log('Decoding converted proof and creating verification inputs.');
// Decode proof values and create input for verification.
const input = new EthInput(decodeConsensusMptProof(ethSP1Proof));
// Compute and verify proof.
logger.log('Computing proof.');
return EthVerifier.compute(input, rawProof);
}
catch (err) {
logger.error(`Error computing proof: ${String(err)}`);
throw err;
}
}
async submit(ethProof) {
logger.log('Submitting a proof.');
try {
await fetchAccount({ publicKey: __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_zkApp, "f").address });
await fetchAccount({
publicKey: __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_senderPrivateKey, "f").toPublicKey(),
});
logger.log('Fetched accounts.');
logger.log('Creating update transaction.');
const updateTx = await Mina.transaction({
sender: __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_senderPrivateKey, "f").toPublicKey(),
fee: __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_txFee, "f"),
memo: `State for slot ${ethProof.publicInput.outputSlot.toString()} set`,
}, async () => {
await __classPrivateFieldGet(this, _MinaEthProcessorSubmitter_zkApp, "f").update(ethProof);
});
await updateTx.prove();
logger.log('Transaction proven.');
const tx = await updateTx.sign([__classPrivateFieldGet(this, _MinaEthProcessorSubmitter_senderPrivateKey, "f")]).send();
logger.log(`Transaction sent to '${__classPrivateFieldGet(this, _MinaEthProcessorSubmitter_network, "f")}'.`);
if (!tx.data) {
throw new Error('Transaction data is undefined');
}
const txId = tx.data.sendZkapp.zkapp.id;
const txHash = tx.data.sendZkapp.zkapp.hash;
if (!txId) {
throw new Error('txId is undefined');
}
return {
txId,
txHash,
};
}
catch (err) {
logger.error(`Error submitting proof: ${String(err)}`);
throw err;
}
}
}
_MinaEthProcessorSubmitter_zkApp = new WeakMap(), _MinaEthProcessorSubmitter_senderPrivateKey = new WeakMap(), _MinaEthProcessorSubmitter_zkAppPrivateKey = new WeakMap(), _MinaEthProcessorSubmitter_network = new WeakMap(), _MinaEthProcessorSubmitter_txFee = new WeakMap(), _MinaEthProcessorSubmitter_testMode = new WeakMap(), _MinaEthProcessorSubmitter_instances = new WeakSet(), _MinaEthProcessorSubmitter_ethProcessorVerificationKey_get = function _MinaEthProcessorSubmitter_ethProcessorVerificationKey_get() {
return this.ethProcessorVerificationKey;
}, _MinaEthProcessorSubmitter_ethVerifierVerificationKey_get = function _MinaEthProcessorSubmitter_ethVerifierVerificationKey_get() {
return this.ethVerifierVerificationKey;
};
//# sourceMappingURL=proofSubmitter.js.map