2025-04-19 15:38:48 +08:00

105 lines
5.0 KiB
JavaScript

import { bigIntToBytes, bytesToHex, concatBytes, int32ToBytes, intToBytes, setLengthLeft, setLengthRight, toBytes, } from './bytes.js';
/**
* @dev Returns the 31-bytes verkle tree stem for a given address and tree index.
* @dev Assumes that the verkle node width = 256
* @param ffi The verkle ffi object from verkle-crypotography-wasm.
* @param address The address to generate the tree key for.
* @param treeIndex The index of the tree to generate the key for. Defaults to 0.
* @return The 31-bytes verkle tree stem as a Uint8Array.
*/
export function getVerkleStem(ffi, address, treeIndex = 0) {
const address32 = setLengthLeft(address.toBytes(), 32);
let treeIndexBytes;
if (typeof treeIndex === 'number') {
treeIndexBytes = setLengthRight(int32ToBytes(Number(treeIndex), true), 32);
}
else {
treeIndexBytes = setLengthRight(bigIntToBytes(BigInt(treeIndex), true).slice(0, 32), 32);
}
const treeStem = ffi.getTreeKey(address32, treeIndexBytes, 0).slice(0, 31);
return treeStem;
}
/**
* Verifies that the executionWitness is valid for the given prestateRoot.
* @param ffi The verkle ffi object from verkle-crypotography-wasm.
* @param prestateRoot The prestateRoot matching the executionWitness.
* @param executionWitness The verkle execution witness.
* @returns {boolean} Whether or not the executionWitness belongs to the prestateRoot.
*/
export function verifyVerkleProof(ffi, prestateRoot, executionWitness) {
return ffi.verifyExecutionWitnessPreState(bytesToHex(prestateRoot), JSON.stringify(executionWitness));
}
export var VerkleLeafType;
(function (VerkleLeafType) {
VerkleLeafType[VerkleLeafType["Version"] = 0] = "Version";
VerkleLeafType[VerkleLeafType["Balance"] = 1] = "Balance";
VerkleLeafType[VerkleLeafType["Nonce"] = 2] = "Nonce";
VerkleLeafType[VerkleLeafType["CodeHash"] = 3] = "CodeHash";
VerkleLeafType[VerkleLeafType["CodeSize"] = 4] = "CodeSize";
})(VerkleLeafType || (VerkleLeafType = {}));
export const VERKLE_VERSION_LEAF_KEY = intToBytes(VerkleLeafType.Version);
export const VERKLE_BALANCE_LEAF_KEY = intToBytes(VerkleLeafType.Balance);
export const VERKLE_NONCE_LEAF_KEY = intToBytes(VerkleLeafType.Nonce);
export const VERKLE_CODE_HASH_LEAF_KEY = intToBytes(VerkleLeafType.CodeHash);
export const VERKLE_CODE_SIZE_LEAF_KEY = intToBytes(VerkleLeafType.CodeSize);
export const VERKLE_HEADER_STORAGE_OFFSET = 64;
export const VERKLE_CODE_OFFSET = 128;
export const VERKLE_NODE_WIDTH = 256;
export const VERKLE_MAIN_STORAGE_OFFSET = BigInt(256) ** BigInt(31);
/**
* @dev Returns the tree key for a given verkle tree stem, and sub index.
* @dev Assumes that the verkle node width = 256
* @param stem The 31-bytes verkle tree stem as a Uint8Array.
* @param subIndex The sub index of the tree to generate the key for as a Uint8Array.
* @return The tree key as a Uint8Array.
*/
export const getVerkleKey = (stem, leaf) => {
switch (leaf) {
case VerkleLeafType.Version:
return concatBytes(stem, VERKLE_VERSION_LEAF_KEY);
case VerkleLeafType.Balance:
return concatBytes(stem, VERKLE_BALANCE_LEAF_KEY);
case VerkleLeafType.Nonce:
return concatBytes(stem, VERKLE_NONCE_LEAF_KEY);
case VerkleLeafType.CodeHash:
return concatBytes(stem, VERKLE_CODE_HASH_LEAF_KEY);
case VerkleLeafType.CodeSize:
return concatBytes(stem, VERKLE_CODE_SIZE_LEAF_KEY);
default:
return concatBytes(stem, leaf);
}
};
export function getVerkleTreeIndexesForStorageSlot(storageKey) {
let position;
if (storageKey < VERKLE_CODE_OFFSET - VERKLE_HEADER_STORAGE_OFFSET) {
position = BigInt(VERKLE_HEADER_STORAGE_OFFSET) + storageKey;
}
else {
position = VERKLE_MAIN_STORAGE_OFFSET + storageKey;
}
const treeIndex = position / BigInt(VERKLE_NODE_WIDTH);
const subIndex = Number(position % BigInt(VERKLE_NODE_WIDTH));
return { treeIndex, subIndex };
}
export function getVerkleTreeIndicesForCodeChunk(chunkId) {
const treeIndex = Math.floor((VERKLE_CODE_OFFSET + chunkId) / VERKLE_NODE_WIDTH);
const subIndex = (VERKLE_CODE_OFFSET + chunkId) % VERKLE_NODE_WIDTH;
return { treeIndex, subIndex };
}
export const getVerkleTreeKeyForCodeChunk = async (address, chunkId, verkleCrypto) => {
const { treeIndex, subIndex } = getVerkleTreeIndicesForCodeChunk(chunkId);
return concatBytes(getVerkleStem(verkleCrypto, address, treeIndex), toBytes(subIndex));
};
export const chunkifyCode = (code) => {
// Pad code to multiple of 31 bytes
if (code.length % 31 !== 0) {
const paddingLength = 31 - (code.length % 31);
code = setLengthRight(code, code.length + paddingLength);
}
throw new Error('Not implemented');
};
export const getVerkleTreeKeyForStorageSlot = async (address, storageKey, verkleCrypto) => {
const { treeIndex, subIndex } = getVerkleTreeIndexesForStorageSlot(storageKey);
return concatBytes(getVerkleStem(verkleCrypto, address, treeIndex), toBytes(subIndex));
};
//# sourceMappingURL=verkle.js.map