@unruggable/gateways
Version:
Trustless Ethereum Multichain CCIP-Read Gateway
86 lines (85 loc) • 3.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ZKEVMProver = void 0;
const constants_1 = require("ethers/constants");
const vm_js_1 = require("../vm.cjs");
const utils_js_1 = require("../utils.cjs");
const types_js_1 = require("./types.cjs");
class ZKEVMProver extends vm_js_1.BlockProver {
static isContract = types_js_1.isContract;
static encodeProof = types_js_1.encodeProof;
static latest = this._createLatest();
async isContract(target) {
target = target.toLowerCase();
if (this.fast) {
return this.cache.get(target, async () => {
const code = await this.provider.getCode(target, this.block);
return code.length > 2;
});
}
return (0, types_js_1.isContract)(await this.getProofs(target));
}
async getStorage(target, slot, fast = this.fast) {
target = target.toLowerCase();
// check to see if we know this target isn't a contract without invoking provider
// this is almost equivalent to: await isContract(target)
const accountProof = await this.proofLRU.touch(target);
if (accountProof && !(0, types_js_1.isContract)(accountProof)) {
return constants_1.ZeroHash;
}
// check to see if we've already have a proof for this value
const storageKey = (0, vm_js_1.makeStorageKey)(target, slot);
const storageProof = await this.proofLRU.touch(storageKey);
if (storageProof) {
return (0, utils_js_1.toPaddedHex)(storageProof.value);
}
if (fast) {
return this.cache.get(storageKey, () => this.provider.getStorage(target, slot, this.block));
}
const proofs = await this.getProofs(target, [slot]);
return (0, types_js_1.isContract)(proofs)
? (0, utils_js_1.toPaddedHex)(proofs.storageProof[0].value)
: constants_1.ZeroHash;
}
async _proveNeed(need, accountRef, slotRefs) {
const m = [...slotRefs];
const accountProof = await this.proofLRU.touch(need.target);
if (accountProof && !(0, types_js_1.isContract)(accountProof))
m.length = 0;
if (!m.length && !need.required)
return;
const proofs = await this.getProofs(need.target, m.map(([slot]) => slot));
if (need.required) {
accountRef.proof = (0, types_js_1.encodeProof)(proofs.codeHashProof);
}
if ((0, types_js_1.isContract)(proofs)) {
m.forEach(([, ref], i) => (ref.proof = (0, types_js_1.encodeProof)(proofs.storageProof[i].proof)));
}
}
async getProofs(target, slots = []) {
// TODO: fix me
const proofs = await this.fetchProofs(target, slots);
this.checkStorageProofs((0, types_js_1.isContract)(proofs), slots, proofs.storageProof);
return proofs;
}
async fetchProofs(target, slots = []) {
const ps = [];
for (let i = 0;;) {
ps.push(this.provider.send('zkevm_getProof', [
target,
slots
.slice(i, (i += this.proofBatchSize))
.map((slot) => (0, utils_js_1.toPaddedHex)(slot)),
this.block,
]));
if (i >= slots.length)
break;
}
const vs = await Promise.all(ps);
for (let i = 1; i < vs.length; i++) {
vs[0].storageProof.push(...vs[i].storageProof);
}
return vs[0];
}
}
exports.ZKEVMProver = ZKEVMProver;