From 493ac12b62b03d984dcf25ff919337c9a434e22b Mon Sep 17 00:00:00 2001 From: Jongwon Park Date: Fri, 14 Mar 2025 07:16:20 +0900 Subject: [PATCH 1/6] feat: remove prev events & use finalized block events --- .../proto/story/evmengine/v1/types/tx.proto | 1 - client/x/evmengine/keeper/abci.go | 19 +-- .../x/evmengine/keeper/abci_internal_test.go | 4 - client/x/evmengine/keeper/msg_server.go | 14 ++- .../keeper/msg_server_internal_test.go | 9 +- client/x/evmengine/keeper/proposal_server.go | 26 ---- client/x/evmengine/types/tx.pb.go | 117 ++++-------------- 7 files changed, 40 insertions(+), 150 deletions(-) diff --git a/client/proto/story/evmengine/v1/types/tx.proto b/client/proto/story/evmengine/v1/types/tx.proto index 07e563db..fff6f2e2 100644 --- a/client/proto/story/evmengine/v1/types/tx.proto +++ b/client/proto/story/evmengine/v1/types/tx.proto @@ -19,7 +19,6 @@ message MsgExecutionPayload { option (cosmos.msg.v1.signer) = "authority"; string authority = 1; bytes execution_payload = 2; - repeated EVMEvent prev_payload_events = 3; } message ExecutionPayloadResponse {} diff --git a/client/x/evmengine/keeper/abci.go b/client/x/evmengine/keeper/abci.go index 23d7ddfc..6d81b2dd 100644 --- a/client/x/evmengine/keeper/abci.go +++ b/client/x/evmengine/keeper/abci.go @@ -137,23 +137,10 @@ func (k *Keeper) PrepareProposal(ctx sdk.Context, req *abci.RequestPreparePropos return nil, errors.Wrap(err, "encode") } - // First, collect all vote extension msgs from the vote provider. - // voteMsgs, err := k.voteProvider.PrepareVotes(ctx, req.LocalLastCommit) - // if err != nil { - // return nil, errors.Wrap(err, "prepare votes") - //} - - // Next, collect all prev payload evm event logs. - evmEvents, err := k.evmEvents(ctx, payloadResp.ExecutionPayload.ParentHash) - if err != nil { - return nil, errors.Wrap(err, "prepare evm event logs") - } - // Then construct the execution payload message. payloadMsg := &types.MsgExecutionPayload{ - Authority: authtypes.NewModuleAddress(types.ModuleName).String(), - ExecutionPayload: payloadData, - PrevPayloadEvents: evmEvents, + Authority: authtypes.NewModuleAddress(types.ModuleName).String(), + ExecutionPayload: payloadData, } // Combine all the votes messages and the payload message into a single transaction. @@ -171,8 +158,6 @@ func (k *Keeper) PrepareProposal(ctx sdk.Context, req *abci.RequestPreparePropos log.Info(ctx, "Proposing new block", "height", req.Height, log.Hex7("execution_block_hash", payloadResp.ExecutionPayload.BlockHash[:]), - // "vote_msgs", len(voteMsgs), - "evm_events", len(evmEvents), ) return &abci.ResponsePrepareProposal{Txs: [][]byte{tx}}, nil diff --git a/client/x/evmengine/keeper/abci_internal_test.go b/client/x/evmengine/keeper/abci_internal_test.go index 6256a888..ee80c229 100644 --- a/client/x/evmengine/keeper/abci_internal_test.go +++ b/client/x/evmengine/keeper/abci_internal_test.go @@ -536,10 +536,6 @@ func assertExecutablePayload(t *testing.T, msg sdk.Msg, ts int64, blockHash comm require.Equal(t, payload.FeeRecipient, validatorAddr) require.Empty(t, payload.Withdrawals) require.Equal(t, payload.Number, height) - - // require.Len(t, executionPayload.PrevPayloadEvents, 1) - // evmLog := executionPayload.PrevPayloadEvents[0] - // require.Equal(t, evmLog.Address, zeroAddr.Bytes()) } func ctxWithAppHash(t *testing.T, appHash common.Hash) (context.Context, *storetypes.KVStoreKey) { diff --git a/client/x/evmengine/keeper/msg_server.go b/client/x/evmengine/keeper/msg_server.go index 62c387e4..f1d1e726 100644 --- a/client/x/evmengine/keeper/msg_server.go +++ b/client/x/evmengine/keeper/msg_server.go @@ -141,14 +141,20 @@ func (s msgServer) ExecutionPayload(ctx context.Context, msg *types.MsgExecution return nil, err } - // Deliver all the previous payload log events - if err := s.evmstakingKeeper.ProcessStakingEvents(ctx, payload.Number-1, msg.PrevPayloadEvents); err != nil { + // get events of the newly finalized block + events, err := s.evmEvents(ctx, payload.BlockHash) + if err != nil { + return nil, errors.Wrap(err, "fetch evm event logs") + } + + // Deliver all the payload log events of the newly finalized block + if err := s.evmstakingKeeper.ProcessStakingEvents(ctx, payload.Number-1, events); err != nil { return nil, errors.Wrap(err, "deliver staking-related event logs") } - if err := s.ProcessUpgradeEvents(ctx, payload.Number-1, msg.PrevPayloadEvents); err != nil { + if err := s.ProcessUpgradeEvents(ctx, payload.Number-1, events); err != nil { return nil, errors.Wrap(err, "deliver upgrade-related event logs") } - if err := s.ProcessUbiEvents(ctx, payload.Number-1, msg.PrevPayloadEvents); err != nil { + if err := s.ProcessUbiEvents(ctx, payload.Number-1, events); err != nil { return nil, errors.Wrap(err, "deliver ubi-related event logs") } diff --git a/client/x/evmengine/keeper/msg_server_internal_test.go b/client/x/evmengine/keeper/msg_server_internal_test.go index baa46868..987fc54c 100644 --- a/client/x/evmengine/keeper/msg_server_internal_test.go +++ b/client/x/evmengine/keeper/msg_server_internal_test.go @@ -248,7 +248,6 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { var payloadData []byte var payloadID engine.PayloadID var block *etypes.Block - var events []*types.EVMEvent cachedCtx, _ := ctx.CacheContext() if tc.setup != nil { @@ -257,14 +256,10 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { if tc.createPayload != nil { block, payloadID, payloadData = tc.createPayload(cachedCtx) } - if tc.createPrevPayloadEvents != nil { - events = tc.createPrevPayloadEvents(cachedCtx, block.Hash()) - } resp, err := msgSrv.ExecutionPayload(cachedCtx, &types.MsgExecutionPayload{ - Authority: authtypes.NewModuleAddress(types.ModuleName).String(), - ExecutionPayload: payloadData, - PrevPayloadEvents: events, + Authority: authtypes.NewModuleAddress(types.ModuleName).String(), + ExecutionPayload: payloadData, }) if tc.expectedError != "" { require.ErrorContains(t, err, tc.expectedError) diff --git a/client/x/evmengine/keeper/proposal_server.go b/client/x/evmengine/keeper/proposal_server.go index 88fc7a07..fb29c2f7 100644 --- a/client/x/evmengine/keeper/proposal_server.go +++ b/client/x/evmengine/keeper/proposal_server.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - "github.com/cosmos/gogoproto/proto" etypes "github.com/ethereum/go-ethereum/core/types" "github.com/piplabs/story/client/x/evmengine/types" @@ -51,17 +50,6 @@ func (s proposalServer) ExecutionPayload(ctx context.Context, msg *types.MsgExec return nil, err } - // Collect local view of the evm logs from the previous payload. - evmEvents, err := s.evmEvents(ctx, payload.ParentHash) - if err != nil { - return nil, errors.Wrap(err, "prepare evm event logs") - } - - // Ensure the proposed evm event logs are equal to the local view. - if err := evmEventsEqual(evmEvents, msg.PrevPayloadEvents); err != nil { - return nil, errors.Wrap(err, "verify prev payload events") - } - return &types.ExecutionPayloadResponse{}, nil } @@ -73,20 +61,6 @@ func NewProposalServer(keeper *Keeper) types.MsgServiceServer { var _ types.MsgServiceServer = proposalServer{} -func evmEventsEqual(a, b []*types.EVMEvent) error { - if len(a) != len(b) { - return errors.New("count mismatch") - } - - for i := range a { - if !proto.Equal(a[i], b[i]) { - return errors.New("log mismatch", "index", i) - } - } - - return nil -} - // compareWithdrawals compares the local peek and received withdrawals. func (s proposalServer) compareWithdrawals(ctx context.Context, actualWithdrawals etypes.Withdrawals) error { maxWithdrawals, err := s.evmstakingKeeper.MaxWithdrawalPerBlock(ctx) diff --git a/client/x/evmengine/types/tx.pb.go b/client/x/evmengine/types/tx.pb.go index 46acbd23..d70cc99c 100644 --- a/client/x/evmengine/types/tx.pb.go +++ b/client/x/evmengine/types/tx.pb.go @@ -31,9 +31,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // MsgExecutionPayload defines the next EVM execution payload and the // logs from previous execution payload. type MsgExecutionPayload struct { - Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - ExecutionPayload []byte `protobuf:"bytes,2,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` - PrevPayloadEvents []*EVMEvent `protobuf:"bytes,3,rep,name=prev_payload_events,json=prevPayloadEvents,proto3" json:"prev_payload_events,omitempty"` + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + ExecutionPayload []byte `protobuf:"bytes,2,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` } func (m *MsgExecutionPayload) Reset() { *m = MsgExecutionPayload{} } @@ -83,13 +82,6 @@ func (m *MsgExecutionPayload) GetExecutionPayload() []byte { return nil } -func (m *MsgExecutionPayload) GetPrevPayloadEvents() []*EVMEvent { - if m != nil { - return m.PrevPayloadEvents - } - return nil -} - type ExecutionPayloadResponse struct { } @@ -205,33 +197,30 @@ func init() { func init() { proto.RegisterFile("story/evmengine/v1/types/tx.proto", fileDescriptor_21bf9c7ed4e0e2c4) } var fileDescriptor_21bf9c7ed4e0e2c4 = []byte{ - // 403 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0x41, 0x8b, 0xd3, 0x40, - 0x14, 0xc7, 0x3b, 0xdb, 0xb5, 0xeb, 0x8e, 0x45, 0x76, 0x67, 0xc1, 0x1d, 0x8a, 0x84, 0x9a, 0x53, - 0x58, 0x31, 0x43, 0xeb, 0xcd, 0xa3, 0x50, 0x10, 0xa4, 0x20, 0x11, 0x3c, 0x78, 0x29, 0xd3, 0xe4, - 0x91, 0x0c, 0x34, 0x99, 0x21, 0x6f, 0x12, 0x92, 0x9b, 0x78, 0xf4, 0xe4, 0x47, 0xd9, 0x0f, 0xe1, - 0xc1, 0xe3, 0x1e, 0x3d, 0x4a, 0x7b, 0xd8, 0xaf, 0x21, 0x9d, 0x6e, 0x5c, 0xa9, 0xd6, 0x5b, 0xde, - 0xe3, 0xf7, 0x7f, 0x79, 0xff, 0x37, 0x7f, 0xfa, 0x0c, 0xad, 0x2e, 0x5b, 0x01, 0x75, 0x0e, 0x45, - 0xaa, 0x0a, 0x10, 0xf5, 0x44, 0xd8, 0xd6, 0x00, 0x0a, 0xdb, 0x84, 0xa6, 0xd4, 0x56, 0x33, 0xee, - 0x90, 0xf0, 0x37, 0x12, 0xd6, 0x93, 0xd0, 0x21, 0xa3, 0xcb, 0x58, 0x63, 0xae, 0x51, 0xe4, 0x98, - 0x6e, 0x75, 0x39, 0xa6, 0x3b, 0x89, 0xff, 0x8d, 0xd0, 0x8b, 0x39, 0xa6, 0xb3, 0x06, 0xe2, 0xca, - 0x2a, 0x5d, 0xbc, 0x93, 0xed, 0x4a, 0xcb, 0x84, 0x3d, 0xa5, 0xa7, 0xb2, 0xb2, 0x99, 0x2e, 0x95, - 0x6d, 0x39, 0x19, 0x93, 0xe0, 0x34, 0xba, 0x6f, 0xb0, 0xe7, 0xf4, 0x1c, 0x3a, 0xc5, 0xc2, 0xec, - 0x24, 0xfc, 0x68, 0x4c, 0x82, 0x61, 0x74, 0x06, 0xfb, 0xa3, 0x22, 0x7a, 0x61, 0x4a, 0xa8, 0x3b, - 0x6e, 0x01, 0x35, 0x14, 0x16, 0x79, 0x7f, 0xdc, 0x0f, 0x1e, 0x4d, 0xfd, 0xf0, 0xd0, 0xce, 0xe1, - 0xec, 0xc3, 0x7c, 0xb6, 0x45, 0xa3, 0xf3, 0xad, 0xfc, 0x6e, 0x9a, 0xeb, 0xe0, 0xab, 0xc7, 0x9f, - 0x6f, 0xaf, 0xaf, 0xee, 0x17, 0xf2, 0x47, 0x94, 0xef, 0x5b, 0x88, 0x00, 0x8d, 0x2e, 0x10, 0x7c, - 0x45, 0x1f, 0x76, 0xa3, 0x18, 0xa7, 0x27, 0x32, 0x49, 0x4a, 0x40, 0x74, 0xa6, 0x86, 0x51, 0x57, - 0xb2, 0x27, 0x74, 0x60, 0xb5, 0x51, 0x31, 0xf2, 0xa3, 0x71, 0x3f, 0x18, 0x46, 0x77, 0x15, 0x63, - 0xf4, 0x38, 0x91, 0x56, 0xf2, 0xbe, 0xc3, 0xdd, 0x37, 0xbb, 0xa4, 0x27, 0xb6, 0x59, 0x64, 0x12, - 0x33, 0x7e, 0xec, 0xda, 0x03, 0xdb, 0xbc, 0x91, 0x98, 0x4d, 0xbf, 0x10, 0x4a, 0xe7, 0x98, 0xbe, - 0x87, 0xb2, 0x56, 0x31, 0xb0, 0x8a, 0x9e, 0xfd, 0x75, 0xd8, 0x17, 0x87, 0x0d, 0xff, 0xe3, 0x1d, - 0x46, 0xd3, 0xff, 0xdc, 0xe7, 0x80, 0xe1, 0xd1, 0x83, 0x4f, 0xb7, 0xd7, 0x57, 0xe4, 0xf5, 0xdb, - 0xef, 0x6b, 0x8f, 0xdc, 0xac, 0x3d, 0xf2, 0x73, 0xed, 0x91, 0xaf, 0x1b, 0xaf, 0x77, 0xb3, 0xf1, - 0x7a, 0x3f, 0x36, 0x5e, 0xef, 0xe3, 0x24, 0x55, 0x36, 0xab, 0x96, 0x61, 0xac, 0x73, 0x61, 0x94, - 0x59, 0xc9, 0x25, 0x8a, 0x5d, 0xba, 0xe2, 0x95, 0x82, 0xc2, 0x8a, 0xe6, 0x8f, 0x98, 0xb9, 0x9f, - 0x2d, 0x07, 0x2e, 0x2e, 0x2f, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0x94, 0x42, 0x36, 0xc4, 0x86, - 0x02, 0x00, 0x00, + // 368 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0x41, 0x8b, 0xda, 0x40, + 0x14, 0xc7, 0x1d, 0xb5, 0x5a, 0x07, 0x29, 0x76, 0x0a, 0x75, 0x08, 0x25, 0x58, 0x4f, 0x62, 0x69, + 0x06, 0xed, 0xad, 0xc7, 0x82, 0x50, 0x28, 0x42, 0x49, 0xa1, 0x87, 0x5e, 0x64, 0x4c, 0x86, 0x64, + 0xc0, 0x64, 0x86, 0xbc, 0x49, 0x48, 0x6e, 0xa5, 0xc7, 0x9e, 0xf6, 0xa3, 0xf8, 0x31, 0xf6, 0xe8, + 0x71, 0x8f, 0x8b, 0x1e, 0xfc, 0x1a, 0xcb, 0x8e, 0xeb, 0xba, 0xb8, 0xeb, 0x2d, 0xef, 0xf1, 0xfb, + 0xe5, 0xcd, 0xfc, 0xe7, 0xe1, 0x8f, 0x60, 0x54, 0x56, 0x31, 0x51, 0x24, 0x22, 0x8d, 0x64, 0x2a, + 0x58, 0x31, 0x61, 0xa6, 0xd2, 0x02, 0x98, 0x29, 0x3d, 0x9d, 0x29, 0xa3, 0x08, 0xb5, 0x88, 0xf7, + 0x88, 0x78, 0xc5, 0xc4, 0xb3, 0x88, 0xd3, 0x0f, 0x14, 0x24, 0x0a, 0x58, 0x02, 0xd1, 0xbd, 0x97, + 0x40, 0x74, 0x50, 0x86, 0x1a, 0xbf, 0x9b, 0x43, 0x34, 0x2b, 0x45, 0x90, 0x1b, 0xa9, 0xd2, 0x9f, + 0xbc, 0x5a, 0x29, 0x1e, 0x92, 0x0f, 0xb8, 0xc3, 0x73, 0x13, 0xab, 0x4c, 0x9a, 0x8a, 0xa2, 0x01, + 0x1a, 0x75, 0xfc, 0x53, 0x83, 0x7c, 0xc2, 0x6f, 0xc5, 0xd1, 0x58, 0xe8, 0x83, 0x42, 0xeb, 0x03, + 0x34, 0xea, 0xfa, 0x3d, 0x71, 0xf6, 0xab, 0xaf, 0x6f, 0xfe, 0xed, 0xd7, 0xe3, 0x93, 0x3c, 0x74, + 0x30, 0x3d, 0x1f, 0xe7, 0x0b, 0xd0, 0x2a, 0x05, 0x31, 0x94, 0xf8, 0xf5, 0xec, 0xf7, 0x7c, 0x56, + 0x88, 0xd4, 0x10, 0x8a, 0xdb, 0x3c, 0x0c, 0x33, 0x01, 0x60, 0x0f, 0xd0, 0xf5, 0x8f, 0x25, 0x79, + 0x8f, 0x5b, 0x46, 0x69, 0x19, 0x00, 0xad, 0x0f, 0x1a, 0xa3, 0xae, 0xff, 0x50, 0x11, 0x82, 0x9b, + 0x21, 0x37, 0x9c, 0x36, 0x2c, 0x6e, 0xbf, 0x49, 0x1f, 0xb7, 0x4d, 0xb9, 0x88, 0x39, 0xc4, 0xb4, + 0x69, 0xdb, 0x2d, 0x53, 0x7e, 0xe7, 0x10, 0x4f, 0xff, 0x23, 0x8c, 0xe7, 0x10, 0xfd, 0x12, 0x59, + 0x21, 0x03, 0x41, 0x72, 0xdc, 0x7b, 0x16, 0xc2, 0x67, 0xef, 0x52, 0x9e, 0xde, 0x0b, 0x99, 0x39, + 0xd3, 0xcb, 0xf8, 0xa5, 0x0b, 0x3b, 0xaf, 0xfe, 0xee, 0xd7, 0x63, 0xf4, 0xed, 0xc7, 0xf5, 0xd6, + 0x45, 0x9b, 0xad, 0x8b, 0x6e, 0xb7, 0x2e, 0xba, 0xda, 0xb9, 0xb5, 0xcd, 0xce, 0xad, 0xdd, 0xec, + 0xdc, 0xda, 0x9f, 0x49, 0x24, 0x4d, 0x9c, 0x2f, 0xbd, 0x40, 0x25, 0x4c, 0x4b, 0xbd, 0xe2, 0x4b, + 0x60, 0x87, 0x45, 0x08, 0x56, 0x52, 0xa4, 0x86, 0x95, 0x4f, 0x36, 0xc2, 0x0e, 0x5b, 0xb6, 0xec, + 0xcb, 0x7e, 0xb9, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x53, 0xf6, 0xe5, 0x3c, 0x31, 0x02, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -337,20 +326,6 @@ func (m *MsgExecutionPayload) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.PrevPayloadEvents) > 0 { - for iNdEx := len(m.PrevPayloadEvents) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.PrevPayloadEvents[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - } if len(m.ExecutionPayload) > 0 { i -= len(m.ExecutionPayload) copy(dAtA[i:], m.ExecutionPayload) @@ -469,12 +444,6 @@ func (m *MsgExecutionPayload) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if len(m.PrevPayloadEvents) > 0 { - for _, e := range m.PrevPayloadEvents { - l = e.Size() - n += 1 + l + sovTx(uint64(l)) - } - } return n } @@ -615,40 +584,6 @@ func (m *MsgExecutionPayload) Unmarshal(dAtA []byte) error { m.ExecutionPayload = []byte{} } iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PrevPayloadEvents", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.PrevPayloadEvents = append(m.PrevPayloadEvents, &EVMEvent{}) - if err := m.PrevPayloadEvents[len(m.PrevPayloadEvents)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) From ddccb9cc13393b78d5742175bf4fb307ba5280c9 Mon Sep 17 00:00:00 2001 From: Jongwon Park Date: Fri, 14 Mar 2025 07:16:51 +0900 Subject: [PATCH 2/6] fix: optimize loop --- client/x/evmengine/keeper/evmmsgs.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/client/x/evmengine/keeper/evmmsgs.go b/client/x/evmengine/keeper/evmmsgs.go index c567f78b..7472c0e0 100644 --- a/client/x/evmengine/keeper/evmmsgs.go +++ b/client/x/evmengine/keeper/evmmsgs.go @@ -43,18 +43,16 @@ func (k *Keeper) evmEvents(ctx context.Context, blockHash common.Hash) ([]*types for _, t := range l.Topics { topics = append(topics, t.Bytes()) } - events = append(events, &types.EVMEvent{ + event := &types.EVMEvent{ Address: l.Address.Bytes(), Topics: topics, Data: l.Data, TxHash: l.TxHash.Bytes(), - }) - } - - for _, event := range events { + } if err := event.Verify(); err != nil { return nil, errors.Wrap(err, "verify event") } + events = append(events, event) } return events, nil From 5b55016261c22579243f72339b904cbe374a7aea Mon Sep 17 00:00:00 2001 From: Jongwon Park Date: Wed, 19 Mar 2025 02:54:56 +0900 Subject: [PATCH 3/6] fix: deprecated proto field --- .../proto/story/evmengine/v1/types/tx.proto | 1 + client/x/evmengine/types/tx.pb.go | 118 ++++++++++++++---- 2 files changed, 93 insertions(+), 26 deletions(-) diff --git a/client/proto/story/evmengine/v1/types/tx.proto b/client/proto/story/evmengine/v1/types/tx.proto index fff6f2e2..a2f3692b 100644 --- a/client/proto/story/evmengine/v1/types/tx.proto +++ b/client/proto/story/evmengine/v1/types/tx.proto @@ -19,6 +19,7 @@ message MsgExecutionPayload { option (cosmos.msg.v1.signer) = "authority"; string authority = 1; bytes execution_payload = 2; + repeated EVMEvent prev_payload_events = 3 [deprecated = true]; } message ExecutionPayloadResponse {} diff --git a/client/x/evmengine/types/tx.pb.go b/client/x/evmengine/types/tx.pb.go index d70cc99c..70bc1424 100644 --- a/client/x/evmengine/types/tx.pb.go +++ b/client/x/evmengine/types/tx.pb.go @@ -31,8 +31,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // MsgExecutionPayload defines the next EVM execution payload and the // logs from previous execution payload. type MsgExecutionPayload struct { - Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - ExecutionPayload []byte `protobuf:"bytes,2,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + ExecutionPayload []byte `protobuf:"bytes,2,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` + PrevPayloadEvents []*EVMEvent `protobuf:"bytes,3,rep,name=prev_payload_events,json=prevPayloadEvents,proto3" json:"prev_payload_events,omitempty"` // Deprecated: Do not use. } func (m *MsgExecutionPayload) Reset() { *m = MsgExecutionPayload{} } @@ -82,6 +83,14 @@ func (m *MsgExecutionPayload) GetExecutionPayload() []byte { return nil } +// Deprecated: Do not use. +func (m *MsgExecutionPayload) GetPrevPayloadEvents() []*EVMEvent { + if m != nil { + return m.PrevPayloadEvents + } + return nil +} + type ExecutionPayloadResponse struct { } @@ -197,30 +206,33 @@ func init() { func init() { proto.RegisterFile("story/evmengine/v1/types/tx.proto", fileDescriptor_21bf9c7ed4e0e2c4) } var fileDescriptor_21bf9c7ed4e0e2c4 = []byte{ - // 368 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0x41, 0x8b, 0xda, 0x40, - 0x14, 0xc7, 0x1d, 0xb5, 0x5a, 0x07, 0x29, 0x76, 0x0a, 0x75, 0x08, 0x25, 0x58, 0x4f, 0x62, 0x69, - 0x06, 0xed, 0xad, 0xc7, 0x82, 0x50, 0x28, 0x42, 0x49, 0xa1, 0x87, 0x5e, 0x64, 0x4c, 0x86, 0x64, - 0xc0, 0x64, 0x86, 0xbc, 0x49, 0x48, 0x6e, 0xa5, 0xc7, 0x9e, 0xf6, 0xa3, 0xf8, 0x31, 0xf6, 0xe8, - 0x71, 0x8f, 0x8b, 0x1e, 0xfc, 0x1a, 0xcb, 0x8e, 0xeb, 0xba, 0xb8, 0xeb, 0x2d, 0xef, 0xf1, 0xfb, - 0xe5, 0xcd, 0xfc, 0xe7, 0xe1, 0x8f, 0x60, 0x54, 0x56, 0x31, 0x51, 0x24, 0x22, 0x8d, 0x64, 0x2a, - 0x58, 0x31, 0x61, 0xa6, 0xd2, 0x02, 0x98, 0x29, 0x3d, 0x9d, 0x29, 0xa3, 0x08, 0xb5, 0x88, 0xf7, - 0x88, 0x78, 0xc5, 0xc4, 0xb3, 0x88, 0xd3, 0x0f, 0x14, 0x24, 0x0a, 0x58, 0x02, 0xd1, 0xbd, 0x97, - 0x40, 0x74, 0x50, 0x86, 0x1a, 0xbf, 0x9b, 0x43, 0x34, 0x2b, 0x45, 0x90, 0x1b, 0xa9, 0xd2, 0x9f, - 0xbc, 0x5a, 0x29, 0x1e, 0x92, 0x0f, 0xb8, 0xc3, 0x73, 0x13, 0xab, 0x4c, 0x9a, 0x8a, 0xa2, 0x01, - 0x1a, 0x75, 0xfc, 0x53, 0x83, 0x7c, 0xc2, 0x6f, 0xc5, 0xd1, 0x58, 0xe8, 0x83, 0x42, 0xeb, 0x03, - 0x34, 0xea, 0xfa, 0x3d, 0x71, 0xf6, 0xab, 0xaf, 0x6f, 0xfe, 0xed, 0xd7, 0xe3, 0x93, 0x3c, 0x74, - 0x30, 0x3d, 0x1f, 0xe7, 0x0b, 0xd0, 0x2a, 0x05, 0x31, 0x94, 0xf8, 0xf5, 0xec, 0xf7, 0x7c, 0x56, - 0x88, 0xd4, 0x10, 0x8a, 0xdb, 0x3c, 0x0c, 0x33, 0x01, 0x60, 0x0f, 0xd0, 0xf5, 0x8f, 0x25, 0x79, - 0x8f, 0x5b, 0x46, 0x69, 0x19, 0x00, 0xad, 0x0f, 0x1a, 0xa3, 0xae, 0xff, 0x50, 0x11, 0x82, 0x9b, - 0x21, 0x37, 0x9c, 0x36, 0x2c, 0x6e, 0xbf, 0x49, 0x1f, 0xb7, 0x4d, 0xb9, 0x88, 0x39, 0xc4, 0xb4, - 0x69, 0xdb, 0x2d, 0x53, 0x7e, 0xe7, 0x10, 0x4f, 0xff, 0x23, 0x8c, 0xe7, 0x10, 0xfd, 0x12, 0x59, - 0x21, 0x03, 0x41, 0x72, 0xdc, 0x7b, 0x16, 0xc2, 0x67, 0xef, 0x52, 0x9e, 0xde, 0x0b, 0x99, 0x39, - 0xd3, 0xcb, 0xf8, 0xa5, 0x0b, 0x3b, 0xaf, 0xfe, 0xee, 0xd7, 0x63, 0xf4, 0xed, 0xc7, 0xf5, 0xd6, - 0x45, 0x9b, 0xad, 0x8b, 0x6e, 0xb7, 0x2e, 0xba, 0xda, 0xb9, 0xb5, 0xcd, 0xce, 0xad, 0xdd, 0xec, - 0xdc, 0xda, 0x9f, 0x49, 0x24, 0x4d, 0x9c, 0x2f, 0xbd, 0x40, 0x25, 0x4c, 0x4b, 0xbd, 0xe2, 0x4b, - 0x60, 0x87, 0x45, 0x08, 0x56, 0x52, 0xa4, 0x86, 0x95, 0x4f, 0x36, 0xc2, 0x0e, 0x5b, 0xb6, 0xec, - 0xcb, 0x7e, 0xb9, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x53, 0xf6, 0xe5, 0x3c, 0x31, 0x02, 0x00, 0x00, + // 406 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xc1, 0x6a, 0xdb, 0x40, + 0x10, 0x86, 0xbd, 0x76, 0xea, 0x34, 0x5b, 0x53, 0x92, 0x0d, 0x34, 0x8b, 0x29, 0xc2, 0xf5, 0x49, + 0xa4, 0x54, 0x8b, 0xdd, 0x5b, 0x8f, 0x01, 0x43, 0xa1, 0x18, 0x8a, 0x0a, 0x39, 0xf4, 0x62, 0xd6, + 0xd2, 0x20, 0x2d, 0x58, 0xda, 0x45, 0xb3, 0x12, 0xd2, 0xad, 0xf4, 0xd8, 0x53, 0x1f, 0x25, 0x8f, + 0x91, 0x63, 0x8e, 0x3d, 0x16, 0xfb, 0x90, 0xd7, 0x28, 0x5e, 0x47, 0x4d, 0x71, 0xeb, 0xde, 0x34, + 0xc3, 0xf7, 0xff, 0x9a, 0x7f, 0x76, 0xe8, 0x2b, 0xb4, 0xba, 0x68, 0x04, 0x54, 0x19, 0xe4, 0x89, + 0xca, 0x41, 0x54, 0x13, 0x61, 0x1b, 0x03, 0x28, 0x6c, 0x1d, 0x98, 0x42, 0x5b, 0xcd, 0xb8, 0x43, + 0x82, 0xdf, 0x48, 0x50, 0x4d, 0x02, 0x87, 0x0c, 0x2f, 0x22, 0x8d, 0x99, 0x46, 0x91, 0x61, 0xb2, + 0xd5, 0x65, 0x98, 0xec, 0x24, 0xe3, 0x5b, 0x42, 0xcf, 0xe7, 0x98, 0xcc, 0x6a, 0x88, 0x4a, 0xab, + 0x74, 0xfe, 0x51, 0x36, 0x2b, 0x2d, 0x63, 0xf6, 0x92, 0x9e, 0xc8, 0xd2, 0xa6, 0xba, 0x50, 0xb6, + 0xe1, 0x64, 0x44, 0xfc, 0x93, 0xf0, 0xb1, 0xc1, 0x5e, 0xd3, 0x33, 0x68, 0x15, 0x0b, 0xb3, 0x93, + 0xf0, 0xee, 0x88, 0xf8, 0x83, 0xf0, 0x14, 0xf6, 0xad, 0xae, 0xe9, 0xb9, 0x29, 0xa0, 0x6a, 0xb9, + 0x05, 0x54, 0x90, 0x5b, 0xe4, 0xbd, 0x51, 0xcf, 0x7f, 0x36, 0x1d, 0x07, 0x87, 0x66, 0x0e, 0x66, + 0xd7, 0xf3, 0xd9, 0x16, 0xbd, 0xea, 0x72, 0x12, 0x9e, 0x6d, 0x2d, 0x1e, 0x1c, 0x5d, 0x17, 0xdf, + 0x3d, 0xff, 0x7a, 0x7f, 0x73, 0xf9, 0x38, 0xd4, 0x78, 0x48, 0xf9, 0x7e, 0x8c, 0x10, 0xd0, 0xe8, + 0x1c, 0x61, 0xac, 0xe8, 0xd3, 0xd6, 0x8e, 0x71, 0x7a, 0x2c, 0xe3, 0xb8, 0x00, 0x44, 0x17, 0x6c, + 0x10, 0xb6, 0x25, 0x7b, 0x41, 0xfb, 0x56, 0x1b, 0x15, 0x21, 0xef, 0x8e, 0x7a, 0xfe, 0x20, 0x7c, + 0xa8, 0x18, 0xa3, 0x47, 0xb1, 0xb4, 0x92, 0xf7, 0x1c, 0xee, 0xbe, 0xd9, 0x05, 0x3d, 0xb6, 0xf5, + 0x22, 0x95, 0x98, 0xf2, 0x23, 0xd7, 0xee, 0xdb, 0xfa, 0xbd, 0xc4, 0x74, 0xfa, 0x8d, 0x50, 0x3a, + 0xc7, 0xe4, 0x13, 0x14, 0x95, 0x8a, 0x80, 0x95, 0xf4, 0xf4, 0xaf, 0xe5, 0xbe, 0x39, 0x1c, 0xfa, + 0x1f, 0x6f, 0x31, 0x9c, 0xfe, 0x67, 0x47, 0x07, 0x02, 0x0f, 0x9f, 0x7c, 0xb9, 0xbf, 0xb9, 0x24, + 0x57, 0x1f, 0x6e, 0xd7, 0x1e, 0xb9, 0x5b, 0x7b, 0xe4, 0xe7, 0xda, 0x23, 0xdf, 0x37, 0x5e, 0xe7, + 0x6e, 0xe3, 0x75, 0x7e, 0x6c, 0xbc, 0xce, 0xe7, 0x49, 0xa2, 0x6c, 0x5a, 0x2e, 0x83, 0x48, 0x67, + 0xc2, 0x28, 0xb3, 0x92, 0x4b, 0x14, 0xbb, 0x0b, 0x8b, 0x56, 0x0a, 0x72, 0x2b, 0xea, 0x3f, 0x4e, + 0xcd, 0xfd, 0x6c, 0xd9, 0x77, 0x27, 0xf3, 0xf6, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3b, 0xee, + 0x21, 0x5e, 0x8a, 0x02, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -326,6 +338,20 @@ func (m *MsgExecutionPayload) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.PrevPayloadEvents) > 0 { + for iNdEx := len(m.PrevPayloadEvents) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PrevPayloadEvents[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } if len(m.ExecutionPayload) > 0 { i -= len(m.ExecutionPayload) copy(dAtA[i:], m.ExecutionPayload) @@ -444,6 +470,12 @@ func (m *MsgExecutionPayload) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } + if len(m.PrevPayloadEvents) > 0 { + for _, e := range m.PrevPayloadEvents { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } return n } @@ -584,6 +616,40 @@ func (m *MsgExecutionPayload) Unmarshal(dAtA []byte) error { m.ExecutionPayload = []byte{} } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PrevPayloadEvents", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PrevPayloadEvents = append(m.PrevPayloadEvents, &EVMEvent{}) + if err := m.PrevPayloadEvents[len(m.PrevPayloadEvents)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) From f742cc49f21b94b171245a8bc74df34ec00c0dc7 Mon Sep 17 00:00:00 2001 From: Jongwon Park Date: Wed, 19 Mar 2025 05:58:43 +0900 Subject: [PATCH 4/6] test: override filter logs to test current block events --- .../x/evmengine/keeper/abci_internal_test.go | 7 +- .../keeper/msg_server_internal_test.go | 88 +++++++++++-------- 2 files changed, 59 insertions(+), 36 deletions(-) diff --git a/client/x/evmengine/keeper/abci_internal_test.go b/client/x/evmengine/keeper/abci_internal_test.go index ee80c229..2e22b2a1 100644 --- a/client/x/evmengine/keeper/abci_internal_test.go +++ b/client/x/evmengine/keeper/abci_internal_test.go @@ -595,6 +595,7 @@ type mockEngineAPI struct { forkchoiceUpdatedV3Func func(context.Context, eengine.ForkchoiceStateV1, *eengine.PayloadAttributes) (eengine.ForkChoiceResponse, error) getPayloadV3Func func(context.Context, eengine.PayloadID) (*eengine.ExecutionPayloadEnvelope, error) newPayloadV3Func func(context.Context, eengine.ExecutableData, []common.Hash, *common.Hash) (eengine.PayloadStatusV1, error) + filterLogsFunc func(context.Context, ethereum.FilterQuery) ([]types.Log, error) // forceInvalidNewPayloadV3 forces the NewPayloadV3 returns an invalid status. forceInvalidNewPayloadV3 bool // forceInvalidForkchoiceUpdatedV3 forces the ForkchoiceUpdatedV3 returns an invalid status. @@ -679,7 +680,11 @@ func (m mockEngineAPI) maybeSync() (eengine.PayloadStatusV1, bool) { } } -func (mockEngineAPI) FilterLogs(context.Context, ethereum.FilterQuery) ([]types.Log, error) { +func (m mockEngineAPI) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { + if m.filterLogsFunc != nil { + return m.filterLogsFunc(ctx, q) + } + return nil, nil } diff --git a/client/x/evmengine/keeper/msg_server_internal_test.go b/client/x/evmengine/keeper/msg_server_internal_test.go index 987fc54c..e148d9dc 100644 --- a/client/x/evmengine/keeper/msg_server_internal_test.go +++ b/client/x/evmengine/keeper/msg_server_internal_test.go @@ -11,9 +11,11 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/common" etypes "github.com/ethereum/go-ethereum/core/types" + fuzz "github.com/google/gofuzz" "github.com/stretchr/testify/require" moduletestutil "github.com/piplabs/story/client/x/evmengine/testutil" @@ -51,7 +53,6 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { ctx, storeKey, storeService := setupCtxStore(t, &header) ctx = ctx.WithExecMode(sdk.ExecModeFinalize) - evmLogProc := mockLogProvider{deliverErr: errors.New("test error")} mockEngine, err := newMockEngineAPI(storeKey, 2) require.NoError(t, err) keeper, err := NewKeeper(cdc, storeService, &mockEngine, mockClient, txConfig, ak, esk, uk, dk) @@ -80,20 +81,32 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { return block, payloadID, payloadData } - createRandomEvents := func(c context.Context, blkHash common.Hash) []*types.EVMEvent { - events, err := evmLogProc.Prepare(c, blkHash) - require.NoError(t, err) - - return events + createRandomEvmEvents := func(c context.Context, blockHash common.Hash) func(ctx context.Context, q ethereum.FilterQuery) ([]etypes.Log, error) { + f := fuzz.NewWithSeed(int64(blockHash[0])) + + var topic common.Hash + f.Fuzz(&topic) + + var txHash common.Hash + f.Fuzz(&txHash) + + return func(ctx context.Context, q ethereum.FilterQuery) ([]etypes.Log, error) { + return []etypes.Log{{ + Address: zeroAddr, + Topics: []common.Hash{topic}, + Data: []byte("data"), + TxHash: txHash, + }}, nil + } } tcs := []struct { - name string - setup func(c context.Context) sdk.Context - createPayload func(c context.Context) (*etypes.Block, engine.PayloadID, []byte) - createPrevPayloadEvents func(c context.Context, blkHash common.Hash) []*types.EVMEvent - expectedError string - postCheck func(c context.Context, block *etypes.Block, payloadID engine.PayloadID) + name string + setup func(c context.Context) sdk.Context + createPayload func(c context.Context) (*etypes.Block, engine.PayloadID, []byte) + createEvmLogs func(ctx context.Context, blockHash common.Hash) func(ctx context.Context, q ethereum.FilterQuery) ([]etypes.Log, error) + expectedError string + postCheck func(c context.Context, block *etypes.Block, payloadID engine.PayloadID) }{ { name: "pass: valid payload", @@ -105,8 +118,8 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { return sdk.UnwrapSDKContext(c) }, - createPayload: createValidPayload, - createPrevPayloadEvents: createRandomEvents, + createPayload: createValidPayload, + createEvmLogs: createRandomEvmEvents, postCheck: func(c context.Context, block *etypes.Block, payloadID engine.PayloadID) { gotPayload, err := mockEngine.GetPayloadV3(c, payloadID) require.NoError(t, err) @@ -156,8 +169,8 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { return block, payloadID, payloadData }, - createPrevPayloadEvents: createRandomEvents, - expectedError: "invalid proposed payload number", + createEvmLogs: createRandomEvmEvents, + expectedError: "invalid proposed payload number", }, { name: "fail: DequeueEligibleWithdrawals error", @@ -180,9 +193,9 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { return sdk.UnwrapSDKContext(ctx) }, - createPayload: createValidPayload, - createPrevPayloadEvents: createRandomEvents, - expectedError: "payload invalid", + createPayload: createValidPayload, + createEvmLogs: createRandomEvmEvents, + expectedError: "payload invalid", }, { name: "fail: ForkchoiceUpdatedV3 returns status invalid", @@ -194,9 +207,9 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { return sdk.UnwrapSDKContext(ctx) }, - createPayload: createValidPayload, - createPrevPayloadEvents: createRandomEvents, - expectedError: "payload invalid", + createPayload: createValidPayload, + createEvmLogs: createRandomEvmEvents, + expectedError: "payload invalid", }, { name: "fail: ProcessStakingEvents error", @@ -208,36 +221,38 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { return sdk.UnwrapSDKContext(ctx) }, - createPayload: createValidPayload, - createPrevPayloadEvents: createRandomEvents, - expectedError: "deliver staking-related event logs", + createPayload: createValidPayload, + createEvmLogs: createRandomEvmEvents, + expectedError: "deliver staking-related event logs", }, { - name: "fail: ProcessUpgradeEvents error", + name: "fail: parsing event error", setup: func(ctx context.Context) sdk.Context { esk.EXPECT().MaxWithdrawalPerBlock(ctx).Return(uint32(0), nil) esk.EXPECT().DequeueEligibleWithdrawals(ctx, gomock.Any()).Return(nil, nil) esk.EXPECT().DequeueEligibleRewardWithdrawals(ctx, gomock.Any()).Return(nil, nil) - esk.EXPECT().ProcessStakingEvents(ctx, gomock.Any(), gomock.Any()).Return(nil) return sdk.UnwrapSDKContext(ctx) }, createPayload: createValidPayload, - createPrevPayloadEvents: func(_ context.Context, _ common.Hash) []*types.EVMEvent { + createEvmLogs: func(ctx context.Context, blockHash common.Hash) func(ctx context.Context, q ethereum.FilterQuery) ([]etypes.Log, error) { // crate invalid upgrade event to trigger ProcessUpgradeEvents failure upgradeAbi, err := bindings.UpgradeEntrypointMetaData.GetAbi() require.NoError(t, err, "failed to load ABI") data, err := upgradeAbi.Events["SoftwareUpgrade"].Inputs.NonIndexed().Pack("test-upgrade", int64(0), "test-info") require.NoError(t, err) - return []*types.EVMEvent{{ - Address: nil, // nil address - Topics: [][]byte{types.SoftwareUpgradeEvent.ID.Bytes()}, - Data: data, - TxHash: dummyHash.Bytes(), - }} + return func(ctx context.Context, q ethereum.FilterQuery) ([]etypes.Log, error) { + return []etypes.Log{{ + Address: zeroAddr, + // use empty bytes (not any of the expected event IDs) to trigger error + Topics: []common.Hash{}, + Data: data, + TxHash: dummyHash, + }}, nil + } }, - expectedError: "deliver upgrade-related event logs", + expectedError: "fetch evm event logs: verify event: empty topics", }, } @@ -256,6 +271,9 @@ func Test_msgServer_ExecutionPayload(t *testing.T) { if tc.createPayload != nil { block, payloadID, payloadData = tc.createPayload(cachedCtx) } + if tc.createEvmLogs != nil { + mockEngine.filterLogsFunc = tc.createEvmLogs(cachedCtx, block.Hash()) + } resp, err := msgSrv.ExecutionPayload(cachedCtx, &types.MsgExecutionPayload{ Authority: authtypes.NewModuleAddress(types.ModuleName).String(), From 50da4acf5a1285fb4c6badf173ed811d8ed335e8 Mon Sep 17 00:00:00 2001 From: Jongwon Park Date: Wed, 19 Mar 2025 05:58:49 +0900 Subject: [PATCH 5/6] refactor: public fns --- client/x/evmengine/keeper/abci.go | 2 +- .../x/evmengine/keeper/abci_internal_test.go | 2 +- client/x/evmengine/keeper/db.go | 24 +++++++++++++------ client/x/evmengine/keeper/db_internal_test.go | 12 +++++----- client/x/evmengine/keeper/evmmsgs.go | 4 ++-- client/x/evmengine/keeper/keeper.go | 2 +- .../evmengine/keeper/keeper_internal_test.go | 16 ++++++------- client/x/evmengine/keeper/msg_server.go | 4 ++-- 8 files changed, 38 insertions(+), 28 deletions(-) diff --git a/client/x/evmengine/keeper/abci.go b/client/x/evmengine/keeper/abci.go index 6d81b2dd..b071c166 100644 --- a/client/x/evmengine/keeper/abci.go +++ b/client/x/evmengine/keeper/abci.go @@ -238,7 +238,7 @@ func (k *Keeper) PostFinalize(ctx sdk.Context) error { // startBuild triggers the building of a new execution payload on top of the current execution head. // It returns the EngineAPI response which contains a status and payload ID. func (k *Keeper) startBuild(ctx context.Context, feeRecipient common.Address, withdrawals []*etypes.Withdrawal, appHash common.Hash, timestamp time.Time) (engine.ForkChoiceResponse, error) { - head, err := k.getExecutionHead(ctx) + head, err := k.GetExecutionHead(ctx) if err != nil { return engine.ForkChoiceResponse{}, errors.Wrap(err, "latest execution block") } diff --git a/client/x/evmengine/keeper/abci_internal_test.go b/client/x/evmengine/keeper/abci_internal_test.go index 2e22b2a1..0c26fd9a 100644 --- a/client/x/evmengine/keeper/abci_internal_test.go +++ b/client/x/evmengine/keeper/abci_internal_test.go @@ -284,7 +284,7 @@ func TestKeeper_PrepareProposal(t *testing.T) { // get the genesis block to build on top of // Get the parent block we will build on top of - head, err := keeper.getExecutionHead(ctx) + head, err := keeper.GetExecutionHead(ctx) require.NoError(t, err) req := &abci.RequestPrepareProposal{ diff --git a/client/x/evmengine/keeper/db.go b/client/x/evmengine/keeper/db.go index eee9c505..af1bb99f 100644 --- a/client/x/evmengine/keeper/db.go +++ b/client/x/evmengine/keeper/db.go @@ -34,8 +34,8 @@ func (k *Keeper) InsertGenesisHead(ctx context.Context, executionBlockHash []byt return nil } -// getExecutionHead returns the current execution head. -func (k *Keeper) getExecutionHead(ctx context.Context) (*ExecutionHead, error) { +// GetExecutionHead returns the current execution head. +func (k *Keeper) GetExecutionHead(ctx context.Context) (*ExecutionHead, error) { head, err := k.headTable.Get(ctx, executionHeadID) if err != nil { return nil, errors.Wrap(err, "get execution head") @@ -44,14 +44,24 @@ func (k *Keeper) getExecutionHead(ctx context.Context) (*ExecutionHead, error) { return head, nil } -// updateExecutionHead updates the execution head with the given payload. -func (k *Keeper) updateExecutionHead(ctx context.Context, payload engine.ExecutableData) error { +// UpdateExecutionHead updates the execution head with the given payload. +func (k *Keeper) UpdateExecutionHead(ctx context.Context, payload engine.ExecutableData) error { + return k.updateExecutionHead(ctx, payload.Number, payload.BlockHash, payload.Timestamp) +} + +func (k *Keeper) UpdateExecutionHeadWithBlock(ctx context.Context, blockHeight uint64, blockHash common.Hash, blockTime uint64) error { + return k.updateExecutionHead(ctx, blockHeight, blockHash, blockTime) +} + +func (k *Keeper) updateExecutionHead( + ctx context.Context, blockHeight uint64, blockHash common.Hash, blockTime uint64, +) error { head := &ExecutionHead{ Id: executionHeadID, CreatedHeight: uint64(sdk.UnwrapSDKContext(ctx).BlockHeight()), - BlockHeight: payload.Number, - BlockHash: payload.BlockHash.Bytes(), - BlockTime: payload.Timestamp, + BlockHeight: blockHeight, + BlockHash: blockHash.Bytes(), + BlockTime: blockTime, } err := k.headTable.Update(ctx, head) diff --git a/client/x/evmengine/keeper/db_internal_test.go b/client/x/evmengine/keeper/db_internal_test.go index 32d0eeda..a322aa08 100644 --- a/client/x/evmengine/keeper/db_internal_test.go +++ b/client/x/evmengine/keeper/db_internal_test.go @@ -14,7 +14,7 @@ func TestKeeper_InsertGenesisHead(t *testing.T) { ctx, keeper := createTestKeeper(t) // make sure the execution head does not exist - _, err := keeper.getExecutionHead(ctx) + _, err := keeper.GetExecutionHead(ctx) require.Error(t, err, "execution head should not exist") // insert genesis head @@ -23,7 +23,7 @@ func TestKeeper_InsertGenesisHead(t *testing.T) { require.NoError(t, err) // make sure the execution head is set correctly - head, err := keeper.getExecutionHead(ctx) + head, err := keeper.GetExecutionHead(ctx) require.NoError(t, err) require.NotNil(t, head, "execution head should exist") require.Equal(t, dummyBlockHash, head.GetBlockHash(), "block hash should match") @@ -39,7 +39,7 @@ func TestKeeper_updateExecutionHead(t *testing.T) { ctx, keeper := createTestKeeper(t) // make sure the execution head does not exist - _, err := keeper.getExecutionHead(ctx) + _, err := keeper.GetExecutionHead(ctx) require.Error(t, err, "execution head should not exist") // insert genesis head @@ -48,13 +48,13 @@ func TestKeeper_updateExecutionHead(t *testing.T) { require.NoError(t, err) // make sure the execution head is set correctly - head, err := keeper.getExecutionHead(ctx) + head, err := keeper.GetExecutionHead(ctx) require.NoError(t, err) require.NotNil(t, head, "execution head should exist") // update the execution head newBlockHash := common.BytesToHash([]byte("new hash")) - err = keeper.updateExecutionHead(ctx, engine.ExecutableData{ + err = keeper.UpdateExecutionHead(ctx, engine.ExecutableData{ Number: 100, BlockHash: newBlockHash, Timestamp: 0, @@ -62,7 +62,7 @@ func TestKeeper_updateExecutionHead(t *testing.T) { require.NoError(t, err) // make sure the execution head is updated correctly - head, err = keeper.getExecutionHead(ctx) + head, err = keeper.GetExecutionHead(ctx) require.NoError(t, err) require.NotNil(t, head, "execution head should exist") require.Equal(t, newBlockHash.Bytes(), head.GetBlockHash(), "block hash should match") diff --git a/client/x/evmengine/keeper/evmmsgs.go b/client/x/evmengine/keeper/evmmsgs.go index 7472c0e0..de9a34cd 100644 --- a/client/x/evmengine/keeper/evmmsgs.go +++ b/client/x/evmengine/keeper/evmmsgs.go @@ -13,8 +13,8 @@ import ( clog "github.com/piplabs/story/lib/log" ) -// evmEvents returns selected EVM log events from the provided block hash. -func (k *Keeper) evmEvents(ctx context.Context, blockHash common.Hash) ([]*types.EVMEvent, error) { +// EvmEvents returns selected EVM log events from the provided block hash. +func (k *Keeper) EvmEvents(ctx context.Context, blockHash common.Hash) ([]*types.EVMEvent, error) { var logs []ethtypes.Log err := retryForever(ctx, func(ctx context.Context) (fetched bool, err error) { logs, err = k.engineCl.FilterLogs(ctx, ethereum.FilterQuery{ diff --git a/client/x/evmengine/keeper/keeper.go b/client/x/evmengine/keeper/keeper.go index 5e971d09..07173c2e 100644 --- a/client/x/evmengine/keeper/keeper.go +++ b/client/x/evmengine/keeper/keeper.go @@ -156,7 +156,7 @@ func (k *Keeper) parseAndVerifyProposedPayload(ctx context.Context, msg *types.M } // Fetch the latest execution head from the local keeper DB. - head, err := k.getExecutionHead(ctx) + head, err := k.GetExecutionHead(ctx) if err != nil { return engine.ExecutableData{}, errors.Wrap(err, "latest execution block") } diff --git a/client/x/evmengine/keeper/keeper_internal_test.go b/client/x/evmengine/keeper/keeper_internal_test.go index 058cb62d..5b292338 100644 --- a/client/x/evmengine/keeper/keeper_internal_test.go +++ b/client/x/evmengine/keeper/keeper_internal_test.go @@ -165,7 +165,7 @@ func TestKeeper_parseAndVerifyProposedPayload(t *testing.T) { { name: "fail: payload parent hash is not equal to head hash", msg: func(c context.Context) *types.MsgExecutionPayload { - execHead, err := keeper.getExecutionHead(c) + execHead, err := keeper.GetExecutionHead(c) require.NoError(t, err) payload, err := ethclient.MakePayload(fuzzer, execHead.GetBlockHeight()+1, uint64(now.Unix()), common.Hash{}, common.Address{}, common.Hash{}, &common.Hash{}) @@ -184,7 +184,7 @@ func TestKeeper_parseAndVerifyProposedPayload(t *testing.T) { { name: "fail: invalid payload timestamp", msg: func(c context.Context) *types.MsgExecutionPayload { - execHead, err := keeper.getExecutionHead(c) + execHead, err := keeper.GetExecutionHead(c) require.NoError(t, err) weekAgo := execHead.GetBlockTime() - 604800 @@ -204,7 +204,7 @@ func TestKeeper_parseAndVerifyProposedPayload(t *testing.T) { { name: "fail: invalid payload random", msg: func(c context.Context) *types.MsgExecutionPayload { - execHead, err := keeper.getExecutionHead(c) + execHead, err := keeper.GetExecutionHead(c) require.NoError(t, err) payload, err := ethclient.MakePayload(fuzzer, execHead.GetBlockHeight()+1, uint64(now.Unix()), execHead.Hash(), common.Address{}, common.Hash{}, &common.Hash{}) @@ -223,7 +223,7 @@ func TestKeeper_parseAndVerifyProposedPayload(t *testing.T) { { name: "fail: invalid authority", msg: func(c context.Context) *types.MsgExecutionPayload { - execHead, err := keeper.getExecutionHead(c) + execHead, err := keeper.GetExecutionHead(c) require.NoError(t, err) payload, err := ethclient.MakePayload(fuzzer, execHead.GetBlockHeight()+1, uint64(now.Unix()), execHead.Hash(), common.Address{}, execHead.Hash(), &common.Hash{}) @@ -242,7 +242,7 @@ func TestKeeper_parseAndVerifyProposedPayload(t *testing.T) { { name: "pass: valid payload", msg: func(c context.Context) *types.MsgExecutionPayload { - execHead, err := keeper.getExecutionHead(c) + execHead, err := keeper.GetExecutionHead(c) require.NoError(t, err) payload, err := ethclient.MakePayload(fuzzer, execHead.GetBlockHeight()+1, uint64(now.Unix()), execHead.Hash(), common.Address{}, execHead.Hash(), &common.Hash{}) @@ -260,10 +260,10 @@ func TestKeeper_parseAndVerifyProposedPayload(t *testing.T) { { name: "pass: valid payload when consensus block time is less than execution block time", setup: func(c context.Context) sdk.Context { - execHead, err := keeper.getExecutionHead(c) + execHead, err := keeper.GetExecutionHead(c) require.NoError(t, err) // update execution head with current block time - err = keeper.updateExecutionHead(c, engine.ExecutableData{ + err = keeper.UpdateExecutionHead(c, engine.ExecutableData{ Number: execHead.GetBlockHeight(), BlockHash: common.BytesToHash(execHead.GetBlockHash()), Timestamp: uint64(now.Unix()), @@ -277,7 +277,7 @@ func TestKeeper_parseAndVerifyProposedPayload(t *testing.T) { return sdkCtx }, msg: func(c context.Context) *types.MsgExecutionPayload { - execHead, err := keeper.getExecutionHead(c) + execHead, err := keeper.GetExecutionHead(c) require.NoError(t, err) payload, err := ethclient.MakePayload(fuzzer, execHead.GetBlockHeight()+1, execHead.GetBlockTime()+1, execHead.Hash(), common.Address{}, execHead.Hash(), &common.Hash{}) diff --git a/client/x/evmengine/keeper/msg_server.go b/client/x/evmengine/keeper/msg_server.go index f1d1e726..c50ae5da 100644 --- a/client/x/evmengine/keeper/msg_server.go +++ b/client/x/evmengine/keeper/msg_server.go @@ -142,7 +142,7 @@ func (s msgServer) ExecutionPayload(ctx context.Context, msg *types.MsgExecution } // get events of the newly finalized block - events, err := s.evmEvents(ctx, payload.BlockHash) + events, err := s.EvmEvents(ctx, payload.BlockHash) if err != nil { return nil, errors.Wrap(err, "fetch evm event logs") } @@ -158,7 +158,7 @@ func (s msgServer) ExecutionPayload(ctx context.Context, msg *types.MsgExecution return nil, errors.Wrap(err, "deliver ubi-related event logs") } - if err := s.updateExecutionHead(ctx, payload); err != nil { + if err := s.UpdateExecutionHead(ctx, payload); err != nil { return nil, errors.Wrap(err, "update execution head") } From 466d539d6256407e3f6ec5a6a8662872b4c5321b Mon Sep 17 00:00:00 2001 From: Jongwon Park Date: Wed, 19 Mar 2025 05:59:15 +0900 Subject: [PATCH 6/6] feat: upgrade handler v1.3.0 --- client/app/upgrades/v1_3_0/constants.go | 18 ++++++++ client/app/upgrades/v1_3_0/upgrades.go | 61 +++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 client/app/upgrades/v1_3_0/constants.go create mode 100644 client/app/upgrades/v1_3_0/upgrades.go diff --git a/client/app/upgrades/v1_3_0/constants.go b/client/app/upgrades/v1_3_0/constants.go new file mode 100644 index 00000000..4ba1bd13 --- /dev/null +++ b/client/app/upgrades/v1_3_0/constants.go @@ -0,0 +1,18 @@ +//nolint:revive,stylecheck // versioning +package v_1_3_0 + +import ( + storetypes "cosmossdk.io/store/types" + + "github.com/piplabs/story/client/app/upgrades" +) + +const ( + UpgradeName = "v1.3.0" +) + +var Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, + CreateUpgradeHandler: CreateUpgradeHandler, + StoreUpgrades: storetypes.StoreUpgrades{}, +} diff --git a/client/app/upgrades/v1_3_0/upgrades.go b/client/app/upgrades/v1_3_0/upgrades.go new file mode 100644 index 00000000..9903452d --- /dev/null +++ b/client/app/upgrades/v1_3_0/upgrades.go @@ -0,0 +1,61 @@ +//nolint:revive,stylecheck // versioning +package v_1_3_0 + +import ( + "context" + + upgradetypes "cosmossdk.io/x/upgrade/types" + + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/ethereum/go-ethereum/common" + + "github.com/piplabs/story/client/app/keepers" + "github.com/piplabs/story/lib/errors" + "github.com/piplabs/story/lib/log" +) + +func CreateUpgradeHandler( + _ *module.Manager, + _ module.Configurator, + keepers *keepers.Keepers, +) upgradetypes.UpgradeHandler { + return func(ctx context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + log.Info(ctx, "Start upgrade v1.3.0") + + // When this handler is triggered at the beginning of block X, we must process the events from block X-1. + // Otherwise, events from block X-1 will be discarded as the upgrade changes the logic to process events of the + // current block once finalized. + + // Get the block hash and events of the previous block. + head, err := keepers.EVMEngKeeper.GetExecutionHead(ctx) + if err != nil { + return nil, errors.Wrap(err, "get execution head") + } + lastBlockHeight := head.GetBlockHeight() + lastBlockHash := common.BytesToHash(head.GetBlockHash()) + + events, err := keepers.EVMEngKeeper.EvmEvents(ctx, lastBlockHash) + if err != nil { + return nil, errors.Wrap(err, "fetch evm event logs") + } + + // Deliver all the payload log events of the block X-1 + if err := keepers.EvmStakingKeeper.ProcessStakingEvents(ctx, lastBlockHeight, events); err != nil { + return nil, errors.Wrap(err, "deliver staking-related event logs") + } + if err := keepers.EVMEngKeeper.ProcessUpgradeEvents(ctx, lastBlockHeight, events); err != nil { + return nil, errors.Wrap(err, "deliver upgrade-related event logs") + } + if err := keepers.EVMEngKeeper.ProcessUbiEvents(ctx, lastBlockHeight, events); err != nil { + return nil, errors.Wrap(err, "deliver ubi-related event logs") + } + + if err := keepers.EVMEngKeeper.UpdateExecutionHeadWithBlock(ctx, lastBlockHeight, lastBlockHash, head.GetBlockTime()); err != nil { + return nil, errors.Wrap(err, "update execution head") + } + + log.Info(ctx, "Upgrade v1.3.0 complete") + + return vm, nil + } +}