Skip to content

Commit e6948ee

Browse files
authored
fix(stf,server/v2/cometbft): fix default events + improve codec handling (#22837)
1 parent a068405 commit e6948ee

File tree

9 files changed

+123
-59
lines changed

9 files changed

+123
-59
lines changed

server/v2/cometbft/abci.go

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"google.golang.org/protobuf/reflect/protoregistry"
1616

1717
"cosmossdk.io/collections"
18-
addresscodec "cosmossdk.io/core/address"
1918
appmodulev2 "cosmossdk.io/core/appmodule/v2"
2019
"cosmossdk.io/core/comet"
2120
corecontext "cosmossdk.io/core/context"
@@ -35,8 +34,6 @@ import (
3534
"cosmossdk.io/server/v2/streaming"
3635
"cosmossdk.io/store/v2/snapshots"
3736
consensustypes "cosmossdk.io/x/consensus/types"
38-
39-
"github.com/cosmos/cosmos-sdk/codec"
4037
)
4138

4239
const (
@@ -52,13 +49,12 @@ type consensus[T transaction.Tx] struct {
5249
logger log.Logger
5350
appName, version string
5451
app appmanager.AppManager[T]
55-
appCodec codec.Codec
56-
txCodec transaction.Codec[T]
5752
store types.Store
5853
listener *appdata.Listener
5954
snapshotManager *snapshots.Manager
6055
streamingManager streaming.Manager
6156
mempool mempool.Mempool[T]
57+
appCodecs AppCodecs[T]
6258

6359
cfg Config
6460
chainID string
@@ -84,16 +80,15 @@ type consensus[T transaction.Tx] struct {
8480
addrPeerFilter types.PeerFilter // filter peers by address and port
8581
idPeerFilter types.PeerFilter // filter peers by node ID
8682

87-
queryHandlersMap map[string]appmodulev2.Handler
88-
getProtoRegistry func() (*protoregistry.Files, error)
89-
consensusAddressCodec addresscodec.Codec
90-
cfgMap server.ConfigMap
83+
queryHandlersMap map[string]appmodulev2.Handler
84+
getProtoRegistry func() (*protoregistry.Files, error)
85+
cfgMap server.ConfigMap
9186
}
9287

9388
// CheckTx implements types.Application.
9489
// It is called by cometbft to verify transaction validity
9590
func (c *consensus[T]) CheckTx(ctx context.Context, req *abciproto.CheckTxRequest) (*abciproto.CheckTxResponse, error) {
96-
decodedTx, err := c.txCodec.Decode(req.Tx)
91+
decodedTx, err := c.appCodecs.TxCodec.Decode(req.Tx)
9792
if err != nil {
9893
return nil, err
9994
}
@@ -325,7 +320,7 @@ func (c *consensus[T]) InitChain(ctx context.Context, req *abciproto.InitChainRe
325320
ctx,
326321
br,
327322
req.AppStateBytes,
328-
c.txCodec)
323+
c.appCodecs.TxCodec)
329324
if err != nil {
330325
return nil, fmt.Errorf("genesis state init failure: %w", err)
331326
}
@@ -392,7 +387,7 @@ func (c *consensus[T]) PrepareProposal(
392387
LastCommit: toCoreExtendedCommitInfo(req.LocalLastCommit),
393388
})
394389

395-
txs, err := c.prepareProposalHandler(ciCtx, c.app, c.txCodec, req)
390+
txs, err := c.prepareProposalHandler(ciCtx, c.app, c.appCodecs.TxCodec, req)
396391
if err != nil {
397392
return nil, err
398393
}
@@ -438,7 +433,7 @@ func (c *consensus[T]) ProcessProposal(
438433
LastCommit: toCoreCommitInfo(req.ProposedLastCommit),
439434
})
440435

441-
err := c.processProposalHandler(ciCtx, c.app, c.txCodec, req)
436+
err := c.processProposalHandler(ciCtx, c.app, c.appCodecs.TxCodec, req)
442437
if err != nil {
443438
c.logger.Error("failed to process proposal", "height", req.Height, "time", req.Time, "hash", fmt.Sprintf("%X", req.Hash), "err", err)
444439
return &abciproto.ProcessProposalResponse{
@@ -567,7 +562,7 @@ func (c *consensus[T]) internalFinalizeBlock(
567562
// TODO(tip): can we expect some txs to not decode? if so, what we do in this case? this does not seem to be the case,
568563
// considering that prepare and process always decode txs, assuming they're the ones providing txs we should never
569564
// have a tx that fails decoding.
570-
decodedTxs, err := decodeTxs(c.logger, req.Txs, c.txCodec)
565+
decodedTxs, err := decodeTxs(c.logger, req.Txs, c.appCodecs.TxCodec)
571566
if err != nil {
572567
return nil, nil, nil, err
573568
}

server/v2/cometbft/abci_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -886,13 +886,15 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock.
886886
}
887887

888888
return &consensus[mock.Tx]{
889-
logger: log.NewNopLogger(),
890-
appName: "testing-app",
891-
app: am,
892-
mempool: mempool,
893-
store: mockStore,
894-
cfg: Config{AppTomlConfig: DefaultAppTomlConfig()},
895-
txCodec: mock.TxCodec{},
889+
logger: log.NewNopLogger(),
890+
appName: "testing-app",
891+
app: am,
892+
mempool: mempool,
893+
store: mockStore,
894+
cfg: Config{AppTomlConfig: DefaultAppTomlConfig()},
895+
appCodecs: AppCodecs[mock.Tx]{
896+
TxCodec: mock.TxCodec{},
897+
},
896898
chainID: "test",
897899
getProtoRegistry: sync.OnceValues(gogoproto.MergedRegistry),
898900
queryHandlersMap: queryHandler,

server/v2/cometbft/grpc.go

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
2828
"github.com/cosmos/cosmos-sdk/codec"
2929
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
30-
"github.com/cosmos/cosmos-sdk/std"
3130
sdk "github.com/cosmos/cosmos-sdk/types"
3231
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
3332
"github.com/cosmos/cosmos-sdk/types/query"
@@ -117,12 +116,13 @@ func (t txServer[T]) GetBlockWithTxs(ctx context.Context, req *txtypes.GetBlockW
117116
}
118117
decodeTxAt := func(i uint64) error {
119118
tx := blockTxs[i]
120-
txb, err := t.clientCtx.TxConfig.TxDecoder()(tx)
121-
fmt.Println("TxDecoder", txb, err)
119+
txb, err := t.txCodec.Decode(tx)
122120
if err != nil {
123121
return err
124122
}
125-
p, err := txb.(interface{ AsTx() (*txtypes.Tx, error) }).AsTx()
123+
124+
// txServer works only with sdk.Tx
125+
p, err := any(txb).(interface{ AsTx() (*txtypes.Tx, error) }).AsTx()
126126
if err != nil {
127127
return err
128128
}
@@ -256,13 +256,19 @@ func (t txServer[T]) Simulate(ctx context.Context, req *txtypes.SimulateRequest)
256256
msgResponses = append(msgResponses, anyMsg)
257257
}
258258

259+
event, err := intoABCIEvents(txResult.Events, map[string]struct{}{}, false)
260+
if err != nil {
261+
return nil, status.Errorf(codes.Unknown, "failed to convert events: %v", err)
262+
}
263+
259264
return &txtypes.SimulateResponse{
260265
GasInfo: &sdk.GasInfo{
261266
GasUsed: txResult.GasUsed,
262267
GasWanted: txResult.GasWanted,
263268
},
264269
Result: &sdk.Result{
265270
MsgResponses: msgResponses,
271+
Events: event,
266272
},
267273
}, nil
268274
}
@@ -273,15 +279,17 @@ func (t txServer[T]) TxDecode(ctx context.Context, req *txtypes.TxDecodeRequest)
273279
return nil, status.Error(codes.InvalidArgument, "invalid empty tx bytes")
274280
}
275281

276-
txb, err := t.clientCtx.TxConfig.TxDecoder()(req.TxBytes)
282+
txb, err := t.txCodec.Decode(req.TxBytes)
277283
if err != nil {
278284
return nil, err
279285
}
280286

281-
tx, err := txb.(interface{ AsTx() (*txtypes.Tx, error) }).AsTx() // TODO: maybe we can break the Tx interface to add this also
287+
// txServer works only with sdk.Tx
288+
tx, err := any(txb).(interface{ AsTx() (*txtypes.Tx, error) }).AsTx()
282289
if err != nil {
283290
return nil, err
284291
}
292+
285293
return &txtypes.TxDecodeResponse{
286294
Tx: tx,
287295
}, nil
@@ -350,7 +358,7 @@ func (t txServer[T]) TxEncodeAmino(_ context.Context, req *txtypes.TxEncodeAmino
350358
var stdTx legacytx.StdTx
351359
err := t.clientCtx.LegacyAmino.UnmarshalJSON([]byte(req.AminoJson), &stdTx)
352360
if err != nil {
353-
return nil, err
361+
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid request %s", err))
354362
}
355363

356364
encodedBytes, err := t.clientCtx.LegacyAmino.Marshal(stdTx)
@@ -466,7 +474,7 @@ func (c *consensus[T]) maybeHandleExternalServices(ctx context.Context, req *abc
466474
if strings.HasPrefix(req.Path, "/cosmos.base.tendermint.v1beta1.Service") {
467475
rpcClient, _ := rpchttp.New(c.cfg.ConfigTomlConfig.RPC.ListenAddress)
468476

469-
cometQServer := cmtservice.NewQueryServer(rpcClient, c.Query, c.consensusAddressCodec)
477+
cometQServer := cmtservice.NewQueryServer(rpcClient, c.Query, c.appCodecs.ConsensusAddressCodec)
470478
paths := strings.Split(req.Path, "/")
471479
if len(paths) <= 2 {
472480
return nil, fmt.Errorf("invalid request path: %s", req.Path)
@@ -516,27 +524,18 @@ func (c *consensus[T]) maybeHandleExternalServices(ctx context.Context, req *abc
516524

517525
// Handle tx service
518526
if strings.HasPrefix(req.Path, "/cosmos.tx.v1beta1.Service") {
519-
// init simple client context
520-
amino := codec.NewLegacyAmino()
521-
std.RegisterLegacyAminoCodec(amino)
522-
txConfig := authtx.NewTxConfig(
523-
c.appCodec,
524-
c.appCodec.InterfaceRegistry().SigningContext().AddressCodec(),
525-
c.appCodec.InterfaceRegistry().SigningContext().ValidatorAddressCodec(),
526-
authtx.DefaultSignModes,
527-
)
528527
rpcClient, _ := client.NewClientFromNode(c.cfg.AppTomlConfig.Address)
529528

529+
// init simple client context
530530
clientCtx := client.Context{}.
531-
WithLegacyAmino(amino).
532-
WithCodec(c.appCodec).
533-
WithTxConfig(txConfig).
531+
WithLegacyAmino(c.appCodecs.LegacyAmino.(*codec.LegacyAmino)).
532+
WithCodec(c.appCodecs.AppCodec).
534533
WithNodeURI(c.cfg.AppTomlConfig.Address).
535534
WithClient(rpcClient)
536535

537536
txService := txServer[T]{
538537
clientCtx: clientCtx,
539-
txCodec: c.txCodec,
538+
txCodec: c.appCodecs.TxCodec,
540539
app: c.app,
541540
consensus: c,
542541
}

server/v2/cometbft/query.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func (c *consensus[T]) handleQueryApp(ctx context.Context, path []string, req *a
5151

5252
switch path[1] {
5353
case "simulate":
54-
tx, err := c.txCodec.Decode(req.Data)
54+
tx, err := c.appCodecs.TxCodec.Decode(req.Data)
5555
if err != nil {
5656
return nil, errorsmod.Wrap(err, "failed to decode tx")
5757
}

server/v2/cometbft/server.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
addresscodec "cosmossdk.io/core/address"
2727
appmodulev2 "cosmossdk.io/core/appmodule/v2"
28+
"cosmossdk.io/core/registry"
2829
"cosmossdk.io/core/server"
2930
"cosmossdk.io/core/transaction"
3031
"cosmossdk.io/log"
@@ -66,14 +67,24 @@ type CometBFTServer[T transaction.Tx] struct {
6667
store types.Store
6768
}
6869

70+
// AppCodecs contains all codecs that the CometBFT server requires
71+
// provided by the application. They are extracted in struct to not be API
72+
// breaking once amino is completely deprecated or new codecs should be added.
73+
type AppCodecs[T transaction.Tx] struct {
74+
TxCodec transaction.Codec[T]
75+
76+
// The following codecs are only required for the gRPC services
77+
AppCodec codec.Codec
78+
LegacyAmino registry.AminoRegistrar
79+
ConsensusAddressCodec addresscodec.Codec
80+
}
81+
6982
func New[T transaction.Tx](
7083
logger log.Logger,
7184
appName string,
7285
store types.Store,
7386
app appmanager.AppManager[T],
74-
appCodec codec.Codec,
75-
txCodec transaction.Codec[T],
76-
consensusAddressCodec addresscodec.Codec,
87+
appCodecs AppCodecs[T],
7788
queryHandlers map[string]appmodulev2.Handler,
7889
decoderResolver decoding.DecoderResolver,
7990
serverOptions ServerOptions[T],
@@ -84,7 +95,7 @@ func New[T transaction.Tx](
8495
serverOptions: serverOptions,
8596
cfgOptions: cfgOptions,
8697
app: app,
87-
txCodec: txCodec,
98+
txCodec: appCodecs.TxCodec,
8899
store: store,
89100
}
90101
srv.logger = logger.With(log.ModuleKey, srv.Name())
@@ -172,8 +183,7 @@ func New[T transaction.Tx](
172183
cfg: srv.config,
173184
store: store,
174185
logger: logger,
175-
txCodec: txCodec,
176-
appCodec: appCodec,
186+
appCodecs: appCodecs,
177187
listener: listener,
178188
snapshotManager: snapshotManager,
179189
streamingManager: srv.serverOptions.StreamingManager,
@@ -192,7 +202,6 @@ func New[T transaction.Tx](
192202
addrPeerFilter: srv.serverOptions.AddrPeerFilter,
193203
idPeerFilter: srv.serverOptions.IdPeerFilter,
194204
cfgMap: cfg,
195-
consensusAddressCodec: consensusAddressCodec,
196205
}
197206

198207
c.optimisticExec = oe.NewOptimisticExecution(

server/v2/stf/stf.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package stf
22

33
import (
44
"context"
5+
"encoding/json"
56
"errors"
67
"fmt"
8+
"strings"
79

810
appmodulev2 "cosmossdk.io/core/appmodule/v2"
911
corecontext "cosmossdk.io/core/context"
@@ -358,12 +360,53 @@ func (s STF[T]) runTxMsgs(
358360
e.EventIndex = int32(j + 1)
359361
events = append(events, e)
360362
}
363+
364+
// add message event
365+
events = append(events, createMessageEvent(msg, int32(i+1), int32(len(execCtx.events)+1)))
361366
}
362367

363368
consumed := execCtx.meter.Limit() - execCtx.meter.Remaining()
364369
return msgResps, consumed, events, nil
365370
}
366371

372+
// Create a message event, with two kv: action, the type url of the message
373+
// and module, the module of the message.
374+
func createMessageEvent(msg transaction.Msg, msgIndex, eventIndex int32) event.Event {
375+
// Assumes that module name is the second element of the msg type URL
376+
// e.g. "cosmos.bank.v1beta1.MsgSend" => "bank"
377+
// It returns an empty string if the input is not a valid type URL
378+
getModuleNameFromTypeURL := func(input string) string {
379+
moduleName := strings.Split(input, ".")
380+
if len(moduleName) > 1 {
381+
return moduleName[1]
382+
}
383+
384+
return ""
385+
}
386+
387+
return event.Event{
388+
MsgIndex: msgIndex,
389+
EventIndex: eventIndex,
390+
Type: "message",
391+
Attributes: func() ([]appdata.EventAttribute, error) {
392+
typeURL := msgTypeURL(msg)
393+
return []appdata.EventAttribute{
394+
{Key: "action", Value: "/" + typeURL},
395+
{Key: "module", Value: getModuleNameFromTypeURL(typeURL)},
396+
}, nil
397+
},
398+
Data: func() (json.RawMessage, error) {
399+
typeURL := msgTypeURL(msg)
400+
attrs := []appdata.EventAttribute{
401+
{Key: "action", Value: "/" + typeURL},
402+
{Key: "module", Value: getModuleNameFromTypeURL(typeURL)},
403+
}
404+
405+
return json.Marshal(attrs)
406+
},
407+
}
408+
}
409+
367410
// preBlock executes the pre block logic.
368411
func (s STF[T]) preBlock(
369412
ctx *executionContext,

0 commit comments

Comments
 (0)