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.
This commit is contained in:
Matthieu Vachon 2024-05-01 13:22:54 -04:00
parent c327b4d7fc
commit f8c889f892
2 changed files with 32 additions and 2 deletions

View file

@ -2274,9 +2274,17 @@ func (m Memory) GetPtr(offset, size int64) []byte {
return nil return nil
} }
if len(m) > int(offset) { if len(m) >= (int(offset) + int(size)) {
return m[offset : offset+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))...)
} }

View file

@ -468,3 +468,25 @@ func blockEvent(height uint64) tracing.BlockEvent {
TD: b(1), 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))
})
}
}