Skip to content

Commit 211c878

Browse files
committed
refactor(octane/evmengine): simplify event processing
1 parent e568a2d commit 211c878

File tree

15 files changed

+299
-101
lines changed

15 files changed

+299
-101
lines changed

e2e/manifests/devnet2.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ multi_omni_evms = true
66
prometheus = true
77
deploy_solve = true
88

9-
feature_flags = ["evm-staking-module"]
9+
feature_flags = ["evm-staking-module","simple-evm-events"]
1010

1111
[node.validator01]
1212
[node.validator02]

e2e/manifests/staging.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ multi_omni_evms = true
44
prometheus = true
55
deploy_solve = true
66

7-
feature_flags = ["evm-staking-module"]
7+
feature_flags = ["evm-staking-module","simple-evm-events"]
88

99
[node.validator01]
1010
[node.validator02]

halo/app/start_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,12 @@ func testCProvider(t *testing.T, ctx context.Context, cprov cprovider.Provider)
165165
xblock, ok, err := cprov.XBlock(ctx, 0, true)
166166
tutil.RequireNoError(t, err)
167167
require.True(t, ok)
168-
require.Len(t, xblock.Msgs, 1)
169-
require.Equal(t, xchain.ShardBroadcast0, xblock.Msgs[0].ShardID)
170-
require.Equal(t, xchain.BroadcastChainID, xblock.Msgs[0].DestChainID)
168+
require.Len(t, xblock.Msgs, 2)
169+
for i, msg := range xblock.Msgs {
170+
require.Equal(t, xchain.ShardBroadcast0, msg.ShardID)
171+
require.Equal(t, xchain.BroadcastChainID, msg.DestChainID)
172+
require.EqualValues(t, i, msg.LogIndex)
173+
}
171174

172175
// Ensure getting latest xblock.
173176
xblock2, ok, err := cprov.XBlock(ctx, xblock.BlockHeight, false)

halo/evmstaking2/keeper/keeper_internal_test.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,7 @@ func TestDeliveryWithBrokenServer(t *testing.T) {
114114

115115
keeper, ctx := setupKeeper(t, deliverInterval, sServerMock)
116116

117-
var hash common.Hash
118-
events, err := evmengkeeper.FetchProcEvents(ctx, ethClientMock, keeper, hash)
117+
events, err := getStakingEvents(ctx, ethClientMock, keeper)
119118
require.NoError(t, err)
120119

121120
expectDelegates := 1
@@ -151,8 +150,7 @@ func TestDeliveryOfInvalidEvents(t *testing.T) {
151150

152151
keeper, ctx := setupKeeper(t, deliverInterval, sServerMock)
153152

154-
var hash common.Hash
155-
events, err := evmengkeeper.FetchProcEvents(ctx, ethClientMock, keeper, hash)
153+
events, err := getStakingEvents(ctx, ethClientMock, keeper)
156154
require.NoError(t, err)
157155

158156
expectDelegates := 1
@@ -231,8 +229,7 @@ func TestHappyPathDelivery(t *testing.T) {
231229

232230
keeper, ctx := setupKeeper(t, deliverInterval, sServerMock)
233231

234-
var hash common.Hash
235-
events, err := evmengkeeper.FetchProcEvents(ctx, ethClientMock, keeper, hash)
232+
events, err := getStakingEvents(ctx, ethClientMock, keeper)
236233
require.NoError(t, err)
237234

238235
expectDelegates := 1
@@ -242,7 +239,7 @@ func TestHappyPathDelivery(t *testing.T) {
242239
require.Len(t, events, expectTotalEvents)
243240

244241
for _, event := range events {
245-
err := keeper.Deliver(ctx, hash, event)
242+
err := keeper.Deliver(ctx, common.Hash{}, event)
246243
require.NoError(t, err)
247244
}
248245

@@ -348,3 +345,11 @@ func setupKeeper(
348345

349346
return k, ctx
350347
}
348+
349+
// getStakingEvents returns the staking events from the mock engine client.
350+
func getStakingEvents(ctx context.Context, cl ethclient.EngineClient, keeper *Keeper) ([]etypes.EVMEvent, error) {
351+
// Enable simple staking to ensure events are in correct order, since FetchProcEvents sorts either by index or address>topic>data.
352+
ctx = feature.WithFlag(ctx, feature.FlagSimpleEVMEvents)
353+
354+
return evmengkeeper.FetchProcEvents(ctx, cl, common.Hash{}, keeper)
355+
}

lib/ethclient/enginemock.go

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ var (
4848

4949
var _ EngineClient = (*engineMock)(nil)
5050

51+
type filterQueryKey struct {
52+
BlockHash common.Hash
53+
Address common.Address
54+
}
55+
5156
// engineMock mocks the Engine API for testing purposes.
5257
type engineMock struct {
5358
Client
@@ -57,7 +62,7 @@ type engineMock struct {
5762
mu sync.Mutex
5863
head *types.Block
5964
pendingLogs map[common.Address][]types.Log
60-
logs map[common.Hash][]types.Log
65+
logs map[filterQueryKey][]types.Log
6166
payloads map[engine.PayloadID]payloadArgs
6267
}
6368

@@ -85,7 +90,8 @@ func WithMockValidatorCreation(pubkey crypto.PubKey) func(*engineMock) {
8590
createValidatorEvent.ID,
8691
common.HexToHash(valAddr.Hex()), // validator
8792
},
88-
Data: data,
93+
Data: data,
94+
Index: 100,
8995
}
9096

9197
mock.pendingLogs[contractAddr] = append(mock.pendingLogs[contractAddr], eventLog)
@@ -118,7 +124,8 @@ func WithMockSelfDelegation(pubkey crypto.PubKey, ether int64) func(*engineMock)
118124
common.HexToHash(valAddr.Hex()), // delegator
119125
common.HexToHash(valAddr.Hex()), // validator
120126
},
121-
Data: data,
127+
Data: data,
128+
Index: 300,
122129
}
123130

124131
mock.pendingLogs[contractAddr] = append(mock.pendingLogs[contractAddr], eventLog)
@@ -133,7 +140,7 @@ func WithPortalRegister(network netconf.Network) func(*engineMock) {
133140
contractAddr := common.HexToAddress(predeploys.PortalRegistry)
134141

135142
var eventLogs []types.Log
136-
for _, chain := range network.EVMChains() {
143+
for i, chain := range network.EVMChains() {
137144
data, err := portalRegEvent.Inputs.NonIndexed().Pack(
138145
chain.DeployHeight,
139146
chain.AttestInterval,
@@ -157,7 +164,8 @@ func WithPortalRegister(network netconf.Network) func(*engineMock) {
157164
topicChainID,
158165
common.BytesToHash(chain.PortalAddress.Bytes()), //nolint:forbidigo // Explicit left padded
159166
},
160-
Data: data,
167+
Data: data,
168+
Index: 200 + uint(i),
161169
}
162170

163171
eventLogs = append(eventLogs, eventLog)
@@ -246,7 +254,7 @@ func NewEngineMock(opts ...func(mock *engineMock)) (EngineClient, error) {
246254
head: genesisBlock,
247255
pendingLogs: make(map[common.Address][]types.Log),
248256
payloads: make(map[engine.PayloadID]payloadArgs),
249-
logs: make(map[common.Hash][]types.Log),
257+
logs: make(map[filterQueryKey][]types.Log),
250258
}
251259

252260
for _, opt := range opts {
@@ -285,25 +293,21 @@ func (m *engineMock) FilterLogs(_ context.Context, q ethereum.FilterQuery) ([]ty
285293
}
286294

287295
addr := q.Addresses[0]
288-
289-
// Ensure we returns the same logs for the same query.
290-
if eventLogs, ok := m.logs[*q.BlockHash]; ok {
291-
var resp []types.Log
292-
for _, eventLog := range eventLogs {
293-
if eventLog.Address == addr {
294-
resp = append(resp, eventLog)
295-
}
296-
}
297-
298-
return resp, nil
296+
key := filterQueryKey{
297+
BlockHash: *q.BlockHash,
298+
Address: addr,
299+
}
300+
// Ensure we return the same logs for the same query.
301+
if eventLogs, ok := m.logs[key]; ok {
302+
return eventLogs, nil
299303
}
300304

301305
eventLogs, ok := m.pendingLogs[addr]
302306
if !ok {
303307
return nil, nil
304308
}
305309

306-
m.logs[*q.BlockHash] = eventLogs
310+
m.logs[key] = eventLogs
307311
delete(m.pendingLogs, addr)
308312

309313
return eventLogs, nil

lib/feature/feature.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
const (
1111
// FlagEVMStakingModule enables the wip EVM Staking Module feature.
1212
FlagEVMStakingModule Flag = "evm-staking-module"
13+
// FlagSimpleEVMEvents enables the simplified EVM events refactor.
14+
FlagSimpleEVMEvents Flag = "simple-evm-events"
1315
)
1416

1517
// enabledFlags holds all globally enabled feature flags. The reason for having it is that
@@ -20,6 +22,7 @@ var enabledFlags sync.Map
2022

2123
var allFlags = map[Flag]bool{
2224
FlagEVMStakingModule: true,
25+
FlagSimpleEVMEvents: true,
2326
}
2427

2528
// Flag is a feature flag.

octane/evmengine/keeper/abci.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/omni-network/omni/lib/cast"
1111
"github.com/omni-network/omni/lib/errors"
12+
"github.com/omni-network/omni/lib/feature"
1213
"github.com/omni-network/omni/lib/log"
1314
"github.com/omni-network/omni/octane/evmengine/types"
1415

@@ -133,10 +134,13 @@ func (k *Keeper) PrepareProposal(ctx sdk.Context, req *abci.RequestPreparePropos
133134
return nil, errors.Wrap(err, "prepare votes")
134135
}
135136

136-
// Next, collect all prev payload evm event logs.
137-
evmEvents, err := k.evmEvents(ctx, payloadResp.ExecutionPayload.ParentHash)
138-
if err != nil {
139-
return nil, errors.Wrap(err, "prepare evm event logs")
137+
// Next, collect all prev payload evm event logs (only if simple-evm-events feature not enabled).
138+
var evmEvents []types.EVMEvent
139+
if !feature.FlagSimpleEVMEvents.Enabled(ctx) {
140+
evmEvents, err = k.evmEvents(ctx, payloadResp.ExecutionPayload.ParentHash)
141+
if err != nil {
142+
return nil, errors.Wrap(err, "prepare evm event logs")
143+
}
140144
}
141145

142146
// Then construct the execution payload message.

octane/evmengine/keeper/abci_internal_test.go

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
attesttypes "github.com/omni-network/omni/halo/attest/types"
1212
"github.com/omni-network/omni/lib/errors"
1313
"github.com/omni-network/omni/lib/ethclient"
14+
"github.com/omni-network/omni/lib/feature"
1415
"github.com/omni-network/omni/lib/k1util"
1516
"github.com/omni-network/omni/lib/tutil"
1617
etypes "github.com/omni-network/omni/octane/evmengine/types"
@@ -202,7 +203,7 @@ func TestKeeper_PrepareProposal(t *testing.T) {
202203

203204
for _, msg := range tx.GetMsgs() {
204205
if _, ok := msg.(*etypes.MsgExecutionPayload); ok {
205-
assertExecutablePayload(t, msg, ts.Unix(), nextBlock.Hash(), frp, uint64(req.Height), 0)
206+
assertExecutablePayload(t, msg, ts.Unix(), nextBlock.Hash(), frp, uint64(req.Height), 0, 1)
206207
}
207208
}
208209
})
@@ -251,7 +252,7 @@ func TestKeeper_PrepareProposal(t *testing.T) {
251252
// assert that the message is an executable payload
252253
for _, msg := range tx.GetMsgs() {
253254
if _, ok := msg.(*etypes.MsgExecutionPayload); ok {
254-
assertExecutablePayload(t, msg, req.Time.Unix(), headHash, frp, head.GetBlockHeight()+1, 0)
255+
assertExecutablePayload(t, msg, req.Time.Unix(), headHash, frp, head.GetBlockHeight()+1, 0, 1)
255256
}
256257
if msgDelegate, ok := msg.(*stypes.MsgDelegate); ok {
257258
require.Equal(t, msgDelegate.Amount, sdk.NewInt64Coin("stake", 100))
@@ -329,10 +330,59 @@ func TestKeeper_PrepareProposal(t *testing.T) {
329330
found = true
330331
expected := [][]byte{commitment1, commitment2}
331332
require.EqualValues(t, expected, payload.BlobCommitments)
332-
assertExecutablePayload(t, msg, req.Time.Unix(), headHash, frp, head.GetBlockHeight()+1, len(expected))
333+
assertExecutablePayload(t, msg, req.Time.Unix(), headHash, frp, head.GetBlockHeight()+1, len(expected), 1)
333334
}
334335
require.True(t, found)
335336
})
337+
338+
t.Run("TestSimpleEvmEvents", func(t *testing.T) {
339+
t.Parallel()
340+
// setup dependencies
341+
ctx, storeService := setupCtxStore(t, nil)
342+
ctx = ctx.WithContext(feature.WithFlag(ctx, feature.FlagSimpleEVMEvents))
343+
344+
cdc := getCodec(t)
345+
txConfig := authtx.NewTxConfig(cdc, nil)
346+
347+
mockEngine, err := newMockEngineAPI(0)
348+
require.NoError(t, err)
349+
350+
ap := mockAddressProvider{
351+
address: common.BytesToAddress([]byte("test")),
352+
}
353+
frp := newRandomFeeRecipientProvider()
354+
keeper, err := NewKeeper(cdc, storeService, &mockEngine, txConfig, ap, frp, mockEventProc{})
355+
require.NoError(t, err)
356+
keeper.SetVoteProvider(mockVEProvider{})
357+
populateGenesisHead(ctx, t, keeper)
358+
359+
// Get the parent block we will build on top of
360+
head, err := keeper.getExecutionHead(ctx)
361+
require.NoError(t, err)
362+
headHash, err := head.Hash()
363+
require.NoError(t, err)
364+
365+
req := &abci.RequestPrepareProposal{
366+
Txs: nil,
367+
Height: int64(2),
368+
Time: time.Now(),
369+
MaxTxBytes: cmttypes.MaxBlockSizeBytes,
370+
}
371+
372+
resp, err := keeper.PrepareProposal(withRandomErrs(t, ctx), req)
373+
tutil.RequireNoError(t, err)
374+
require.NotNil(t, resp)
375+
376+
// decode the txn and get the messages
377+
tx, err := txConfig.TxDecoder()(resp.Txs[0])
378+
require.NoError(t, err)
379+
380+
for _, msg := range tx.GetMsgs() {
381+
if _, ok := msg.(*etypes.MsgExecutionPayload); ok {
382+
assertExecutablePayload(t, msg, req.Time.Unix(), headHash, frp, head.GetBlockHeight()+1, 0, 0)
383+
}
384+
}
385+
})
336386
}
337387

338388
func TestOptimistic(t *testing.T) {
@@ -402,6 +452,7 @@ func assertExecutablePayload(
402452
frp etypes.FeeRecipientProvider,
403453
height uint64,
404454
blobs int,
455+
events int,
405456
) {
406457
t.Helper()
407458
executionPayload, ok := msg.(*etypes.MsgExecutionPayload)
@@ -417,9 +468,11 @@ func assertExecutablePayload(
417468
require.Empty(t, payload.Withdrawals)
418469
require.Equal(t, payload.Number, height)
419470

420-
require.Len(t, executionPayload.PrevPayloadEvents, 1)
421-
evmLog := executionPayload.PrevPayloadEvents[0]
422-
require.Equal(t, evmLog.Address, zeroAddr.Bytes())
471+
require.Len(t, executionPayload.PrevPayloadEvents, events)
472+
if events > 0 {
473+
evmLog := executionPayload.PrevPayloadEvents[0]
474+
require.Equal(t, evmLog.Address, zeroAddr.Bytes())
475+
}
423476

424477
require.Len(t, executionPayload.BlobCommitments, blobs)
425478
}

0 commit comments

Comments
 (0)