@axiom-crypto/tools
Version:
Useful data, field, and byte manipulation tools for Axiom.
335 lines (334 loc) • 12.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeBeaconValidatorsSubquery = exports.decodeSolidityNestedMappingSubquery = exports.decodeReceiptSubquery = exports.decodeTxSubquery = exports.decodeStorageSubquery = exports.decodeAccountSubquery = exports.decodeHeaderSubquery = exports.decodeResult = exports.decodeFeeData = exports.decodeCallback = exports.decodeComputeQuery = exports.decodeDataQuery = exports.decodeFullQueryV2 = exports.decodeQueryV2 = void 0;
const constants_1 = require("../../constants");
const byteStringReader_1 = require("../../utils/byteStringReader");
const constants_2 = require("./constants");
const types_1 = require("./types");
/**
* Decodes a query string into an AxiomV2Query object
* @param query The query as a bytes hex string without the first byte (version number)
* @returns The decoded query as a QueryV2 object
*/
function decodeQueryV2(query) {
const reader = new byteStringReader_1.ByteStringReader(query);
const sourceChainId = reader.readBytes(8);
const caller = reader.readBytes(20);
const dataQueryHash = reader.readBytes(32);
const computeQuery = decodeComputeQuery(reader);
if (!computeQuery) {
console.warn(`Unable to decode compute query at index ${reader.currentIdx}`);
return null;
}
const callback = decodeCallback(reader);
if (!callback) {
console.warn(`Unable to decode callback at index ${reader.currentIdx}`);
return null;
}
const feeData = decodeFeeData(reader);
if (!feeData) {
console.warn(`Unable to decode fee data at index ${reader.currentIdx}`);
return null;
}
const userSalt = reader.readBytes(32);
const refundee = reader.readBytes(20);
if (!reader.validateAllBytesRead()) {
console.warn(`All nibbles not read: ${reader.currentIdx} / ${reader.byteString.length}`);
return null;
}
return {
version: constants_2.ConstantsV2.VERSION,
sourceChainId,
caller,
dataQueryHash,
computeQuery,
callback,
userSalt,
feeData,
refundee,
};
}
exports.decodeQueryV2 = decodeQueryV2;
function decodeFullQueryV2(query) {
const reader = new byteStringReader_1.ByteStringReader(query);
// Need to include version here because it is not called by the decodeQuery function
const version = reader.readInt(1);
if (version !== constants_2.ConstantsV2.VERSION) {
throw new Error(`Invalid version number: ${version}`);
}
const sourceChainId = reader.readBytes(8);
const caller = reader.readBytes(20);
const dataQuery = decodeDataQuery(reader);
if (!dataQuery) {
console.warn(`Unable to decode data query at index ${reader.currentIdx}`);
return null;
}
const computeQuery = decodeComputeQuery(reader);
if (!computeQuery) {
console.warn(`Unable to decode compute query at index ${reader.currentIdx}`);
return null;
}
const callback = decodeCallback(reader);
if (!callback) {
console.warn(`Unable to decode callback at index ${reader.currentIdx}`);
return null;
}
const feeData = decodeFeeData(reader);
if (!feeData) {
console.warn(`Unable to decode fee data at index ${reader.currentIdx}`);
return null;
}
const userSalt = reader.readBytes(32);
const refundee = reader.readBytes(20);
if (!reader.validateAllBytesRead()) {
console.warn(`All nibbles not read: ${reader.currentIdx} / ${reader.byteString.length}`);
return null;
}
return {
version,
sourceChainId,
caller,
dataQuery,
computeQuery,
callback,
userSalt,
feeData,
refundee,
};
}
exports.decodeFullQueryV2 = decodeFullQueryV2;
function decodeDataQuery(reader) {
const sourceChainId = reader.readBytes(8);
const subqueryLen = reader.readInt(2);
const subqueries = [];
for (let i = 0; i < subqueryLen; i++) {
const type = reader.readInt(2);
switch (type) {
case types_1.DataSubqueryType.Header:
const headerSubquery = decodeHeaderSubquery(reader);
if (!headerSubquery) {
console.warn(`Unable to decode header subquery at index ${reader.currentIdx}`);
return null;
}
subqueries.push({
type: types_1.DataSubqueryType.Header,
subqueryData: headerSubquery,
});
break;
case types_1.DataSubqueryType.Account:
const accountSubquery = decodeAccountSubquery(reader);
if (!accountSubquery) {
console.warn(`Unable to decode account subquery at index ${reader.currentIdx}`);
return null;
}
subqueries.push({
type: types_1.DataSubqueryType.Account,
subqueryData: accountSubquery,
});
break;
case types_1.DataSubqueryType.Storage:
const storageSubquery = decodeStorageSubquery(reader);
if (!storageSubquery) {
console.warn(`Unable to decode storage subquery at index ${reader.currentIdx}`);
return null;
}
subqueries.push({
type: types_1.DataSubqueryType.Storage,
subqueryData: storageSubquery,
});
break;
case types_1.DataSubqueryType.Transaction:
const txSubquery = decodeTxSubquery(reader);
if (!txSubquery) {
console.warn(`Unable to decode tx subquery at index ${reader.currentIdx}`);
return null;
}
subqueries.push({
type: types_1.DataSubqueryType.Transaction,
subqueryData: txSubquery,
});
break;
case types_1.DataSubqueryType.Receipt:
const receiptSubquery = decodeReceiptSubquery(reader);
if (!receiptSubquery) {
console.warn(`Unable to decode receipt subquery at index ${reader.currentIdx}`);
return null;
}
subqueries.push({
type: types_1.DataSubqueryType.Receipt,
subqueryData: receiptSubquery,
});
break;
case types_1.DataSubqueryType.SolidityNestedMapping:
const solidityNestedMappingSubquery = decodeSolidityNestedMappingSubquery(reader);
if (!solidityNestedMappingSubquery) {
console.warn(`Unable to decode solidity nested mapping subquery at index ${reader.currentIdx}`);
return null;
}
subqueries.push({
type: types_1.DataSubqueryType.SolidityNestedMapping,
subqueryData: solidityNestedMappingSubquery,
});
break;
case types_1.DataSubqueryType.BeaconValidator:
const beaconValidatorSubquery = decodeBeaconValidatorsSubquery(reader);
if (!beaconValidatorSubquery) {
console.warn(`Unable to decode beacon validator subquery at index ${reader.currentIdx}`);
return null;
}
subqueries.push({
type: types_1.DataSubqueryType.BeaconValidator,
subqueryData: beaconValidatorSubquery,
});
break;
default:
throw new Error(`Unknown subquery type ${type} at index ${reader.currentIdx}`);
}
}
// We do not check all bytes are read here because we are passing in a querySlice that is
// longer than the actual dataQuery.
return {
sourceChainId,
subqueries,
};
}
exports.decodeDataQuery = decodeDataQuery;
function decodeComputeQuery(reader) {
const k = reader.readInt(1);
const resultLen = reader.readInt(2);
if (k === 0) {
return {
k,
resultLen,
vkey: [],
computeProof: "",
};
}
const vkeyLen = reader.readInt(1);
const vkey = reader.readFixedLenBytes32(vkeyLen);
const computeProof = reader.readVarLenBytes(constants_1.AxiomV2CircuitConstant.UserProofLenBytes);
return {
k,
resultLen,
vkey,
computeProof,
};
}
exports.decodeComputeQuery = decodeComputeQuery;
function decodeCallback(reader) {
const target = reader.readBytes(20);
const extraData = reader.readVarLenBytes(2);
return {
target,
extraData,
};
}
exports.decodeCallback = decodeCallback;
function decodeFeeData(reader) {
const maxFeePerGas = reader.readBytes(8);
const callbackGasLimit = reader.readInt(4);
const overrideAxiomQueryFee = reader.readBytes(32);
return {
maxFeePerGas,
callbackGasLimit,
overrideAxiomQueryFee,
};
}
exports.decodeFeeData = decodeFeeData;
function decodeResult(query) {
const reader = new byteStringReader_1.ByteStringReader(query);
const sourceChainId = reader.readBytes(8);
const dataResultsRoot = reader.readBytes(32);
const dataResultsPoseidonRoot = reader.readBytes(32);
const computeResultsHash = reader.readBytes(32);
if (!reader.validateAllBytesRead()) {
return null;
}
return {
sourceChainId,
dataResultsRoot,
dataResultsPoseidonRoot,
computeResultsHash,
};
}
exports.decodeResult = decodeResult;
function decodeHeaderSubquery(reader) {
const blockNumber = reader.readInt(4);
const fieldIdx = reader.readInt(4);
return {
blockNumber,
fieldIdx,
};
}
exports.decodeHeaderSubquery = decodeHeaderSubquery;
function decodeAccountSubquery(reader) {
const blockNumber = reader.readInt(4);
const addr = reader.readBytes(20);
const fieldIdx = reader.readInt(4);
return {
blockNumber,
addr,
fieldIdx,
};
}
exports.decodeAccountSubquery = decodeAccountSubquery;
function decodeStorageSubquery(reader) {
const blockNumber = reader.readInt(4);
const addr = reader.readBytes(20);
const slot = reader.readBytes(32);
return {
blockNumber,
addr,
slot,
};
}
exports.decodeStorageSubquery = decodeStorageSubquery;
function decodeTxSubquery(reader) {
const blockNumber = reader.readInt(4);
const txIdx = reader.readInt(2);
const fieldOrCalldataIdx = reader.readInt(4);
return {
blockNumber,
txIdx,
fieldOrCalldataIdx,
};
}
exports.decodeTxSubquery = decodeTxSubquery;
function decodeReceiptSubquery(reader) {
const blockNumber = reader.readInt(4);
const txIdx = reader.readInt(2);
const fieldOrLogIdx = reader.readInt(4);
const topicOrDataOrAddressIdx = reader.readInt(4);
const eventSchema = reader.readBytes(32);
return {
blockNumber,
txIdx,
fieldOrLogIdx,
topicOrDataOrAddressIdx,
eventSchema,
};
}
exports.decodeReceiptSubquery = decodeReceiptSubquery;
function decodeSolidityNestedMappingSubquery(reader) {
const blockNumber = reader.readInt(4);
const addr = reader.readBytes(20);
const mappingSlot = reader.readBytes(32);
const mappingDepth = reader.readInt(1);
let keys = [];
for (let i = 0; i < mappingDepth; i++) {
keys.push(reader.readBytes(32));
}
return {
blockNumber,
addr,
mappingSlot,
mappingDepth,
keys,
};
}
exports.decodeSolidityNestedMappingSubquery = decodeSolidityNestedMappingSubquery;
function decodeBeaconValidatorsSubquery(reader) {
// WIP
return {};
}
exports.decodeBeaconValidatorsSubquery = decodeBeaconValidatorsSubquery;