From 841db33f6b38b78bf026e50b6eb1c561bdeba8cb Mon Sep 17 00:00:00 2001 From: harkamal Date: Wed, 9 Oct 2024 17:30:04 +0530 Subject: [PATCH] modify the ivc accumulator code for smartcontract comaptible compute and add log proofing capabilities by multiple filters --- packages/vm/src/runTx.ts | 42 +++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/vm/src/runTx.ts b/packages/vm/src/runTx.ts index b66ab1e3e5..eb1cec8a45 100644 --- a/packages/vm/src/runTx.ts +++ b/packages/vm/src/runTx.ts @@ -23,6 +23,7 @@ import { } from '@ethereumjs/util' import debugDefault from 'debug' import { keccak256 } from 'ethereum-cryptography/keccak.js' +import { sha256 } from 'ethereum-cryptography/sha256.js' import { Bloom } from './bloom/index.js' import { emitEVMProfile } from './emitEVMProfile.js' @@ -774,10 +775,22 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise { } async function accumulateIVCLogs(vm: VM, number: bigint, logs: Log[]) { + // keep all declarations here for ease of movement and diff + const LOG_ADDRESS_STORAGE_SLOT = setLengthLeft(new Uint8Array([0]), 32) + const LOG_TOPICS_STORAGE_SLOT = setLengthLeft(new Uint8Array([1]), 32) + const LOG_ADDRESS_TOPICS_STORAGE_SLOT = setLengthLeft(new Uint8Array([2]), 32) + + const commonSHA256 = vm.common.customCrypto.sha256 ?? sha256 const ivcContractAddress = new Address( bigIntToAddressBytes(vm.common.param('ivcPredeployAddress')), ) + async function accumulateLog(key: Uint8Array, logRoot: Uint8Array) { + const prevRoot = setLengthLeft(await vm.stateManager.getStorage(ivcContractAddress, key), 32) + const newRoot = commonSHA256(concatBytes(logRoot, prevRoot)) + await vm.stateManager.putStorage(ivcContractAddress, key, newRoot) + } + if ((await vm.stateManager.getAccount(ivcContractAddress)) === undefined) { // store with nonce of 1 to prevent 158 cleanup const ivcContract = new Account() @@ -791,20 +804,27 @@ async function accumulateIVCLogs(vm: VM, number: bigint, logs: Log[]) { topics: log[1], data: log[2], } - const logRoot = ssz.Log.hashTreeRoot(sszLog) + + // Allow eth_getLogs proof via `address` filter + // abi.encode(log.address, LOG_ADDRESS_STORAGE_SLOT) + const paddedAddress = setLengthLeft(sszLog.address, 32) + const addressKey = keccak256(concatBytes(paddedAddress, LOG_ADDRESS_STORAGE_SLOT)) + await accumulateLog(addressKey, logRoot) + for (const topic of sszLog.topics) { - // should be 32 bytes but 0 bytes in case value doesn't exist so just left pad - const prevTopicRoot = setLengthLeft( - await vm.stateManager.getStorage(ivcContractAddress, topic), - 32, + // Allow eth_getLogs proof via `topics` filter + // abi.encode(topic, LOG_TOPICS_STORAGE_SLOT) + const topicKey = keccak256(concatBytes(topic, LOG_TOPICS_STORAGE_SLOT)) + await accumulateLog(topicKey, logRoot) + + // Allow eth_getLogs proof via combined `address` + `topics` filter + // abi.encode(log.address, topic) + const addressAndTopic = keccak256(concatBytes(paddedAddress, topic)) + const addressAndTopicKey = keccak256( + concatBytes(addressAndTopic, LOG_ADDRESS_TOPICS_STORAGE_SLOT), ) - const newTopicRoot = ssz.IVCEntry.hashTreeRoot({ - prevTopicRoot, - number, - logRoot, - }) - await vm.stateManager.putStorage(ivcContractAddress, topic, newTopicRoot) + await accumulateLog(addressAndTopicKey, logRoot) } } }