From f8c889f892b79c7830e2dc0dd280758675b07a79 Mon Sep 17 00:00:00 2001 From: Matthieu Vachon Date: Wed, 1 May 2024 13:22:54 -0400 Subject: [PATCH] Fixed Kecakke256 computation panics in some transaction state The EVM does memory expansion **after** notifying us about OnOpcode which we use to compute Keccak256 pre-images now. This creates problem when we want to retrieve the preimage data because the memory is not expanded yet but in the EVM is going to work because the memory is going to be expanded before the operation is actually executed so the memory will be of the correct size. In this situation, we must pad with zeroes when the memory is not big enough. --- eth/tracers/firehose.go | 12 ++++++++++-- eth/tracers/firehose_test.go | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/eth/tracers/firehose.go b/eth/tracers/firehose.go index e0731efc4a..34b00e81c0 100644 --- a/eth/tracers/firehose.go +++ b/eth/tracers/firehose.go @@ -2274,9 +2274,17 @@ func (m Memory) GetPtr(offset, size int64) []byte { return nil } - if len(m) > int(offset) { + if len(m) >= (int(offset) + int(size)) { return m[offset : offset+size] } - return nil + // The EVM does memory expansion **after** notifying us about OnOpcode which we use + // to compute Keccak256 pre-images now. This creates problem when we want to retrieve + // the preimage data because the memory is not expanded yet but in the EVM is going to + // work because the memory is going to be expanded before the operation is actually + // executed so the memory will be of the correct size. + // + // In this situtation, we must pad with zeroes when the memory is not big enough. + reminder := m[offset:] + return append(reminder, make([]byte, int(size)-len(reminder))...) } diff --git a/eth/tracers/firehose_test.go b/eth/tracers/firehose_test.go index d703addd05..7961419e9f 100644 --- a/eth/tracers/firehose_test.go +++ b/eth/tracers/firehose_test.go @@ -468,3 +468,25 @@ func blockEvent(height uint64) tracing.BlockEvent { TD: b(1), } } + +func TestMemory_GetPtr(t *testing.T) { + type args struct { + offset int64 + size int64 + } + tests := []struct { + name string + m Memory + args args + want []byte + }{ + {"memory is just a bit too small", Memory([]byte{1, 2, 3}), args{0, 4}, []byte{1, 2, 3, 0}}, + {"memory is flushed with request", Memory([]byte{1, 2, 3, 4}), args{0, 4}, []byte{1, 2, 3, 4}}, + {"memory is just a bit too big", Memory([]byte{1, 2, 3, 4, 5}), args{0, 4}, []byte{1, 2, 3, 4}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, tt.m.GetPtr(tt.args.offset, tt.args.size)) + }) + } +}