@@ -23,6 +23,7 @@ import {
23
23
} from '@ethereumjs/util'
24
24
import debugDefault from 'debug'
25
25
import { keccak256 } from 'ethereum-cryptography/keccak.js'
26
+ import { sha256 } from 'ethereum-cryptography/sha256.js'
26
27
27
28
import { Bloom } from './bloom/index.js'
28
29
import { emitEVMProfile } from './emitEVMProfile.js'
@@ -774,10 +775,22 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
774
775
}
775
776
776
777
async function accumulateIVCLogs ( vm : VM , number : bigint , logs : Log [ ] ) {
778
+ // keep all declarations here for ease of movement and diff
779
+ const LOG_ADDRESS_STORAGE_SLOT = setLengthLeft ( new Uint8Array ( [ 0 ] ) , 32 )
780
+ const LOG_TOPICS_STORAGE_SLOT = setLengthLeft ( new Uint8Array ( [ 1 ] ) , 32 )
781
+ const LOG_ADDRESS_TOPICS_STORAGE_SLOT = setLengthLeft ( new Uint8Array ( [ 2 ] ) , 32 )
782
+
783
+ const commonSHA256 = vm . common . customCrypto . sha256 ?? sha256
777
784
const ivcContractAddress = new Address (
778
785
bigIntToAddressBytes ( vm . common . param ( 'ivcPredeployAddress' ) ) ,
779
786
)
780
787
788
+ async function accumulateLog ( key : Uint8Array , logRoot : Uint8Array ) {
789
+ const prevRoot = setLengthLeft ( await vm . stateManager . getStorage ( ivcContractAddress , key ) , 32 )
790
+ const newRoot = commonSHA256 ( concatBytes ( logRoot , prevRoot ) )
791
+ await vm . stateManager . putStorage ( ivcContractAddress , key , newRoot )
792
+ }
793
+
781
794
if ( ( await vm . stateManager . getAccount ( ivcContractAddress ) ) === undefined ) {
782
795
// store with nonce of 1 to prevent 158 cleanup
783
796
const ivcContract = new Account ( )
@@ -791,20 +804,27 @@ async function accumulateIVCLogs(vm: VM, number: bigint, logs: Log[]) {
791
804
topics : log [ 1 ] ,
792
805
data : log [ 2 ] ,
793
806
}
794
-
795
807
const logRoot = ssz . Log . hashTreeRoot ( sszLog )
808
+
809
+ // Allow eth_getLogs proof via `address` filter
810
+ // abi.encode(log.address, LOG_ADDRESS_STORAGE_SLOT)
811
+ const paddedAddress = setLengthLeft ( sszLog . address , 32 )
812
+ const addressKey = keccak256 ( concatBytes ( paddedAddress , LOG_ADDRESS_STORAGE_SLOT ) )
813
+ await accumulateLog ( addressKey , logRoot )
814
+
796
815
for ( const topic of sszLog . topics ) {
797
- // should be 32 bytes but 0 bytes in case value doesn't exist so just left pad
798
- const prevTopicRoot = setLengthLeft (
799
- await vm . stateManager . getStorage ( ivcContractAddress , topic ) ,
800
- 32 ,
816
+ // Allow eth_getLogs proof via `topics` filter
817
+ // abi.encode(topic, LOG_TOPICS_STORAGE_SLOT)
818
+ const topicKey = keccak256 ( concatBytes ( topic , LOG_TOPICS_STORAGE_SLOT ) )
819
+ await accumulateLog ( topicKey , logRoot )
820
+
821
+ // Allow eth_getLogs proof via combined `address` + `topics` filter
822
+ // abi.encode(log.address, topic)
823
+ const addressAndTopic = keccak256 ( concatBytes ( paddedAddress , topic ) )
824
+ const addressAndTopicKey = keccak256 (
825
+ concatBytes ( addressAndTopic , LOG_ADDRESS_TOPICS_STORAGE_SLOT ) ,
801
826
)
802
- const newTopicRoot = ssz . IVCEntry . hashTreeRoot ( {
803
- prevTopicRoot,
804
- number,
805
- logRoot,
806
- } )
807
- await vm . stateManager . putStorage ( ivcContractAddress , topic , newTopicRoot )
827
+ await accumulateLog ( addressAndTopicKey , logRoot )
808
828
}
809
829
}
810
830
}
0 commit comments