@nori-zk/mina-token-bridge
Version:
Nori ethereum state settelment and nETH token bridge zkApp
171 lines (169 loc) • 8.63 kB
JavaScript
import { Logger, LogPrinter } from 'esm-iso-logger';
import { buildExampleProofCreateArgument, buildExampleProofSeriesCreateArguments, } from '../constructExampleProofs.js';
import { NoriTokenBridgeSubmitter } from '../proofSubmitter.js';
import { wait } from '../txWait.js';
import { PrivateKey } from 'o1js';
import { CacheType, decodeConsensusMptProof, extractEthTokenBridgeAddressFromSP1Proof, extractGenesisRootFromSP1Proof, } from '@nori-zk/o1js-zk-utils';
import os from 'os';
import { resolve } from 'path';
import { mkdirSync, rmSync } from 'fs';
import { getNewMinaLiteNetAccountSK } from './testUtils.js';
new LogPrinter('TestNoriTokenBridge');
process.env.MINA_NETWORK = process.env.MINA_NETWORK || 'lightnet';
process.env.MINA_RPC_NETWORK_URL =
process.env.MINA_RPC_NETWORK_URL || 'http://localhost:8080/graphql';
process.env.MINA_ARCHIVE_RPC_URL =
process.env.MINA_ARCHIVE_RPC_URL || 'http://localhost:8282';
const logger = new Logger('JestNoriTokenBridge');
describe('NoriTokenBridgeSubmitter Integration Test', () => {
function getRandomCacheDir(prefix = 'mina-eth-processor-cache') {
const randomSuffix = `${Date.now()}-${Math.floor(Math.random() * 1_000_000)}`;
const cacheDir = resolve(os.tmpdir(), `${prefix}-${randomSuffix}`);
mkdirSync(cacheDir, { recursive: true });
const cacheConfig = {
type: CacheType.FileSystem,
dir: cacheDir,
};
return cacheConfig;
}
void getRandomCacheDir;
function removeCacheDir(cacheConfig) {
rmSync(cacheConfig.dir, { recursive: true, force: true });
}
void removeCacheDir;
// Read only cache idea did not work indicating that the cache written to disk
// is simply not reconstructing the same in memory state as when created from an empty cache.
/*const cacheDir = resolve(os.tmpdir(), 'mina-eth-processor-cache');
const readOnlyCacheConfig: FileSystemCacheConfig = {
type: CacheType.ReadOnlyFileSystem,
dir: cacheDir,
};
beforeAll(async () => {
logger.info(`Creating fresh cache directory: '${cacheDir}'`);
rmSync(cacheDir, { recursive: true, force: true });
mkdirSync(cacheDir, { recursive: true });
const cacheConfig: FileSystemCacheConfig = {
type: CacheType.FileSystem,
dir: cacheDir,
};
const proofSubmitter = new NoriTokenBridgeSubmitter(cacheConfig);
logger.info('Compiling cache.');
await proofSubmitter.compileContracts();
logger.info('Compiled cache.');
});
afterAll(() => {
rmSync(cacheDir, { recursive: true, force: true });
});*/
test('should run the proof submission process correctly', async () => {
// Generate a random contract key
process.env.NORI_MINA_TOKEN_BRIDGE_PRIVATE_KEY = PrivateKey.toBase58(PrivateKey.random());
// Generate a random MINA_SENDER_PRIVATE_KEY
process.env.MINA_SENDER_PRIVATE_KEY = await getNewMinaLiteNetAccountSK();
//const cacheDir = getRandomCacheDir();
try {
// Construct a NoriTokenBridgeSubmitter
const proofSubmitter = new NoriTokenBridgeSubmitter(
//cacheDir // readOnlyCacheConfig
);
// Establish the network
await proofSubmitter.networkSetUp();
// Compile contracts.
await proofSubmitter.compileContracts();
// Get proof
const proofArgument = buildExampleProofCreateArgument();
// Deploy contract
const decoded = decodeConsensusMptProof(proofArgument.sp1PlonkProof);
await proofSubmitter.deployContract(decoded.inputStoreHash, extractEthTokenBridgeAddressFromSP1Proof(proofArgument), extractGenesisRootFromSP1Proof(proofArgument));
// Build proof.
const updateArgs = await proofSubmitter.createProof(proofArgument);
// Submit proof.
const result = await proofSubmitter.submit(updateArgs);
// Wait for finalization
await wait(result.txId, process.env.MINA_RPC_NETWORK_URL);
logger.log('Awaited finalization succesfully.');
}
finally {
// removeCacheDir(cacheDir);
}
}, 10000000);
test('should perform a series of proof submissions', async () => {
// Generate a random contract key
process.env.NORI_MINA_TOKEN_BRIDGE_PRIVATE_KEY = PrivateKey.toBase58(PrivateKey.random());
// Generate a random MINA_SENDER_PRIVATE_KEY
process.env.MINA_SENDER_PRIVATE_KEY = await getNewMinaLiteNetAccountSK();
// const cacheDir = getRandomCacheDir();
try {
// Construct a NoriTokenBridgeSubmitter
const proofSubmitter = new NoriTokenBridgeSubmitter(
// cacheDir // readOnlyCacheConfig
);
// Establish the network
await proofSubmitter.networkSetUp();
// Compile contracts.
await proofSubmitter.compileContracts();
// Get proofs
const seriesExamples = buildExampleProofSeriesCreateArguments();
// Deploy contract
const decoded = decodeConsensusMptProof(seriesExamples[0].sp1PlonkProof);
await proofSubmitter.deployContract(decoded.inputStoreHash, extractEthTokenBridgeAddressFromSP1Proof(seriesExamples[0]), extractGenesisRootFromSP1Proof(seriesExamples[0]));
// Build and submit proofs
let i = 1;
for (const example of seriesExamples) {
logger.log(`Running Example ${i} -------------------------------------------------------`);
// Build proof.
const updateArgs = await proofSubmitter.createProof(example);
// Submit proof.
const result = await proofSubmitter.submit(updateArgs);
logger.log(`txHash: ${result.txHash}`);
// Wait for finalization
await wait(result.txId, process.env.MINA_RPC_NETWORK_URL);
i++;
}
}
finally {
// removeCacheDir(cacheDir);
}
}, 10000000);
test('should invoke a hash validation issue when we skip transition proofs', async () => {
// Generate a random contract key
process.env.NORI_MINA_TOKEN_BRIDGE_PRIVATE_KEY = PrivateKey.toBase58(PrivateKey.random());
// Generate a random MINA_SENDER_PRIVATE_KEY
process.env.MINA_SENDER_PRIVATE_KEY = await getNewMinaLiteNetAccountSK();
// const cacheDir = getRandomCacheDir();
try {
// Construct a NoriTokenBridgeSubmitter
const proofSubmitter = new NoriTokenBridgeSubmitter(
// cacheDir // readOnlyCacheConfig
);
// Establish the network
await proofSubmitter.networkSetUp();
// Compile contracts.
await proofSubmitter.compileContracts();
// Get proof
const seriesExamples = buildExampleProofSeriesCreateArguments();
// Deploy contract
const decoded = decodeConsensusMptProof(seriesExamples[0].sp1PlonkProof);
await proofSubmitter.deployContract(decoded.inputStoreHash, extractEthTokenBridgeAddressFromSP1Proof(seriesExamples[0]), extractGenesisRootFromSP1Proof(seriesExamples[0]));
// Build and submit proofs
logger.log(`Running Example 1 -------------------------------------------------------`);
// Create proof 0
const updateArgs0 = await proofSubmitter.createProof(seriesExamples[0]);
// Submit proof 0.
const result0 = await proofSubmitter.submit(updateArgs0);
logger.log(`txHash: ${result0.txHash}`);
// Wait for finalization
await wait(result0.txId, process.env.MINA_RPC_NETWORK_URL);
logger.log(`Running Example 3 -------------------------------------------------------`);
logger.verbose(`Expecting a failure in the next test as we skip a transition proof the input hash for the 3rd example, wont be the same as the output hash from the 1st example`);
// Create proof 2
const updateArgs2 = await proofSubmitter.createProof(seriesExamples[2]);
// Submit proof 2.
await expect(proofSubmitter.submit(updateArgs2)).rejects.toThrow();
}
finally {
// removeCacheDir(cacheDir);
}
}, 10000000);
// TODO add integration test for redeploy FIXME
});
//# sourceMappingURL=proofSubmitter.integration.spec.js.map