@unruggable/gateways
Version:
Trustless Ethereum Multichain CCIP-Read Gateway
122 lines (121 loc) • 5.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.UnfinalizedLineaRollup = void 0;
const rollup_js_1 = require("../rollup.cjs");
const crypto_1 = require("ethers/crypto");
const contract_1 = require("ethers/contract");
const LineaProver_js_1 = require("./LineaProver.cjs");
const types_js_1 = require("./types.cjs");
const utils_js_1 = require("../utils.cjs");
class UnfinalizedLineaRollup extends rollup_js_1.AbstractRollup {
minAgeBlocks;
L1MessageService;
constructor(providers, config, minAgeBlocks) {
super(providers);
this.minAgeBlocks = minAgeBlocks;
this.L1MessageService = new contract_1.Contract(config.L1MessageService, types_js_1.ROLLUP_ABI, this.provider1);
}
// WARNING: this doesn't work because the stateRoots are sparse merkle
// and the block stateRoots are merkle-patricia
// requirements for operation:
// 1. shomei node with unfinalized proof generation
// 2. shomei stateRoot to l2Block indexer
// this is likely too inefficient and requires external stateRoot => blockHash indexer
// async findL2BlockBefore(beforeTimestamp: number) {
// const step = 1000;
// let block = await fetchBlock(this.provider2);
// while (block && parseInt(block.timestamp) > beforeTimestamp) {
// console.log(parseInt(block.number), block.hash);
// block = await fetchBlock(this.provider2, parseInt(block.number) - step);
// }
// if (!block) throw new Error(`expected block before: ${beforeTimestamp}`);
// return parseInt(block.number) + step - 1;
// }
// async findL2BlockWithStateRoot(
// beforeTimestamp: number,
// stateRoot: HexString32
// ) {
// const step = 100;
// for (
// let i = await this.findL2BlockBefore(beforeTimestamp);
// i >= 0;
// i -= step
// ) {
// const start = Math.max(0, i - step);
// const blocks = await Promise.all(
// Array.from({ length: i - start }, (_, i) =>
// fetchBlock(this.provider2, start + i)
// )
// );
// console.log(start, i);
// const block = blocks.find((x) => x.stateRoot === stateRoot);
// if (block) return BigInt(block.number);
// }
// throw new Error(`unable to find block with stateRoot: ${stateRoot}`);
// }
get unfinalized() {
return true;
}
async fetchLatestCommitIndex() {
const l1BlockInfo = await (0, utils_js_1.fetchBlock)(this.provider1, this.latestBlockTag);
const l1BlockNumber = parseInt(l1BlockInfo.number) - this.minAgeBlocks;
const step = this.getLogsStepSize;
for (let i = l1BlockNumber; i >= 0; i -= step) {
const logs = await this.L1MessageService.queryFilter(this.L1MessageService.filters.DataSubmittedV3(), i < step ? 0 : i + 1 - step, i);
if (logs.length)
return BigInt(logs[logs.length - 1].blockNumber);
}
throw new Error(`no earlier shnarf: ${l1BlockNumber}`);
}
async _fetchParentCommitIndex(commit) {
const [event] = await this.L1MessageService.queryFilter(this.L1MessageService.filters.DataSubmittedV3(null, commit.parentShnarf));
return event ? BigInt(event.blockNumber) : -1n;
}
async _fetchCommit(index) {
const [event] = await this.L1MessageService.queryFilter(this.L1MessageService.filters.DataSubmittedV3(), index, index);
if (!event)
throw new Error(`no DataSubmittedV3`);
const tx = await event.getTransaction();
if (!tx || !tx.blockNumber || !tx.blobVersionedHashes) {
throw new Error(`no submit tx: ${event.transactionHash}`);
}
const desc = this.L1MessageService.interface.parseTransaction(tx);
if (!desc)
throw new Error(`unable to parse tx`);
const blobs = desc.args.blobSubmissionData;
if (!blobs.length)
throw new Error('expected blobs');
const parentShnarf = desc.args.parentShnarf;
let computedShnarf = parentShnarf;
let abiEncodedTuple;
for (let i = 0; i < blobs.length; i++) {
const blob = blobs[i];
const currentDataEvaluationPoint = (0, crypto_1.keccak256)(utils_js_1.ABI_CODER.encode(['bytes32', 'bytes32'], [blob.snarkHash, tx.blobVersionedHashes[i]]));
abiEncodedTuple = utils_js_1.ABI_CODER.encode(['bytes32', 'bytes32', 'bytes32', 'bytes32', 'uint256'], [
computedShnarf,
blob.snarkHash,
blob.finalStateRootHash,
currentDataEvaluationPoint,
blob.dataEvaluationClaim,
]);
computedShnarf = (0, crypto_1.keccak256)(abiEncodedTuple);
}
if (computedShnarf !== desc.args.finalBlobShnarf) {
throw new Error('shnarf mismatch');
}
throw new Error(`block number from shnarf not implemented`);
return {
index,
prover: new LineaProver_js_1.LineaProver(this.provider2, 0),
abiEncodedTuple,
parentShnarf,
};
}
encodeWitness(commit, proofSeq) {
return utils_js_1.ABI_CODER.encode(['(uint256, bytes, bytes[], bytes)'], [[commit.index, commit.abiEncodedTuple, proofSeq.proofs, proofSeq.order]]);
}
windowFromSec(sec) {
return Math.ceil(sec / utils_js_1.MAINNET_BLOCK_SEC); // units of L1Block
}
}
exports.UnfinalizedLineaRollup = UnfinalizedLineaRollup;