@nori-zk/ethprocessor
Version:
zkApp for verifying SP1 Helios Nori proof and storing latest execution state root on Mina
86 lines (84 loc) • 3.64 kB
JavaScript
import { Bytes, Field, Poseidon, Struct, UInt8 } from 'o1js';
import { Bytes20, Bytes32 } from '../types.js';
export function dummyAddress(byte) {
const arr = new Uint8Array(20).fill(byte);
return Bytes20.from(arr);
}
export function dummyValue(byte) {
const arr = new Uint8Array(32).fill(byte);
return Bytes32.from(arr);
}
export function nonProvableStorageSlotLeafHash(addr, value) {
const addrBytes = addr.toBytes();
const valueBytes = value.toBytes();
const firstFieldBytes = new Uint8Array(32);
firstFieldBytes.set(addrBytes, 0); // first 20 bytes from address
firstFieldBytes[20] = valueBytes[0]; // 21st byte from value
const secondFieldBytes = new Uint8Array(32);
secondFieldBytes.set(valueBytes.slice(1, 32), 0); // remaining 31 bytes from value
const firstField = Field.fromBytes(Array.from(firstFieldBytes));
const secondField = Field.fromBytes(Array.from(secondFieldBytes));
return Poseidon.hash([firstField, secondField]);
}
// Build leaf hashes from pairs of (Address, FixedBytes32)
export function buildLeavesNonProvable(pairs) {
return pairs.map(([addr, val]) => nonProvableStorageSlotLeafHash(addr, val));
}
export class ProvableLeafObject extends Struct({
bytes20: Bytes20.provable,
bytes32: Bytes32.provable,
}) {
}
export function provableLeafContentsHash(leafContents) {
const addressBytes = leafContents.bytes20.bytes; // UInt8[]
const valueBytes = leafContents.bytes32.bytes; // UInt8[]
/*Provable.asProver(() => {
Provable.log('addressBytes', addressBytes);
Provable.log('valueBytes', valueBytes);
});*/
// We want 20 bytes from addrBytes + 1 byte from valueBytes + remaining 31 bytes from valueBytes
// firstFieldBytes: 20 bytes from addressBytes + 1 byte from valueBytes
const firstFieldBytes = [];
for (let i = 0; i < 20; i++) {
firstFieldBytes.push(addressBytes[i]);
}
firstFieldBytes.push(valueBytes[0]);
for (let i = 21; i < 32; i++) {
firstFieldBytes.push(UInt8.zero); // static pad to 32
}
// secondFieldBytes: remaining 31 bytes from valueBytes (1 to 31)
const secondFieldBytes = [];
for (let i = 1; i < 32; i++) {
secondFieldBytes.push(valueBytes[i]);
}
// already 31 elements; add 1 zero to reach 32
secondFieldBytes.push(UInt8.zero);
// Convert UInt8[] to Bytes (provable bytes)
const firstBytes = Bytes.from(firstFieldBytes);
const secondBytes = Bytes.from(secondFieldBytes);
// Extract the first field (there should only ever be one here)
/*Provable.asProver(() => {
Provable.log('firstBytes.toFields()', firstBytes.toFields());
Provable.log('secondBytes.toFields()', secondBytes.toFields());
});*
// this is assuming big endian ??
/*let firstField = new Field(0);
let secondField = new Field(0);
for (let i = 0; i < 32; i++) {
firstField = firstField.mul(256).add(firstBytes.bytes[i].value);
secondField = secondField.mul(256).add(secondBytes.bytes[i].value);
}*/
// implement little endian here instead...
let firstField = new Field(0);
let secondField = new Field(0);
for (let i = 31; i >= 0; i--) {
firstField = firstField.mul(256).add(firstBytes.bytes[i].value);
secondField = secondField.mul(256).add(secondBytes.bytes[i].value);
}
/*Provable.asProver(() => {
Provable.log('(provable)firstField', firstField.toBigInt());
Provable.log('(provable)secondField', secondField.toBigInt());
});*/
return Poseidon.hash([firstField, secondField]);
}
//# sourceMappingURL=testUtils.js.map