From c67a32efcd369dc018d3d05df146ea424876af1a Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Mon, 18 Nov 2024 13:13:02 +0100 Subject: [PATCH] simulate --- server/v2/cometbft/grpc.go | 124 +++++++++++++++++++++++++++++-- simapp/v2/go.mod | 2 +- simapp/v2/simdv2/cmd/commands.go | 4 +- 3 files changed, 123 insertions(+), 7 deletions(-) diff --git a/server/v2/cometbft/grpc.go b/server/v2/cometbft/grpc.go index 94a17a9adf28..44781a0868a2 100644 --- a/server/v2/cometbft/grpc.go +++ b/server/v2/cometbft/grpc.go @@ -1,23 +1,36 @@ package cometbft import ( + "context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" cmtv1beta1 "cosmossdk.io/api/cosmos/base/tendermint/v1beta1" - "cosmossdk.io/core/address" - "cosmossdk.io/server/v2/cometbft/client/rpc" + "cosmossdk.io/core/transaction" + errorsmod "cosmossdk.io/errors/v2" + + "github.com/cosmos/gogoproto/proto" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" ) // GRPCServiceRegistrar returns a function that registers the CometBFT gRPC service +// Those services are defined for backward compatibility. +// Eventually, they will be removed in favor of the new gRPC services. func (c *Consensus[T]) GRPCServiceRegistrar( - cometRPC rpc.CometRPC, - consensusAddressCodec address.ConsensusAddressCodec, + clientCtx client.Context, ) func(srv *grpc.Server) error { return func(srv *grpc.Server) error { - cmtservice.RegisterServiceServer(srv, cmtservice.NewQueryServer(cometRPC, c.Query, consensusAddressCodec)) + cmtservice.RegisterServiceServer(srv, cmtservice.NewQueryServer(clientCtx.Client, c.Query, clientCtx.ConsensusAddressCodec)) + txtypes.RegisterServiceServer(srv, txServer[T]{clientCtx, c}) + return nil } } @@ -66,3 +79,104 @@ var CometBFTAutoCLIDescriptor = &autocliv1.ServiceCommandDescriptor{ }, }, } + +type txServer[T transaction.Tx] struct { + clientCtx client.Context + consensus *Consensus[T] +} + +// BroadcastTx implements tx.ServiceServer. +func (t txServer[T]) BroadcastTx(ctx context.Context, req *txtypes.BroadcastTxRequest) (*txtypes.BroadcastTxResponse, error) { + return client.TxServiceBroadcast(ctx, t.clientCtx, req) +} + +// GetBlockWithTxs implements tx.ServiceServer. +func (t txServer[T]) GetBlockWithTxs(context.Context, *txtypes.GetBlockWithTxsRequest) (*txtypes.GetBlockWithTxsResponse, error) { + panic("unimplemented") +} + +// GetTx implements tx.ServiceServer. +func (t txServer[T]) GetTx(context.Context, *txtypes.GetTxRequest) (*txtypes.GetTxResponse, error) { + panic("unimplemented") +} + +// GetTxsEvent implements tx.ServiceServer. +func (t txServer[T]) GetTxsEvent(context.Context, *txtypes.GetTxsEventRequest) (*txtypes.GetTxsEventResponse, error) { + panic("unimplemented") +} + +// Simulate implements tx.ServiceServer. +func (t txServer[T]) Simulate(ctx context.Context, req *txtypes.SimulateRequest) (*txtypes.SimulateResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid empty tx") + } + + txBytes := req.TxBytes + if txBytes == nil && req.Tx != nil { + // This block is for backwards-compatibility. + // We used to support passing a `Tx` in req. But if we do that, sig + // verification might not pass, because the .Marshal() below might not + // be the same marshaling done by the client. + var err error + txBytes, err = proto.Marshal(req.Tx) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid tx; %v", err) + } + } + + if txBytes == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty txBytes is not allowed") + } + + tx, err := t.consensus.txCodec.Decode(txBytes) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to decode tx") + } + + txResult, _, err := t.consensus.app.Simulate(ctx, tx) + if err != nil { + return nil, status.Errorf(codes.Unknown, "%v with gas used: '%d'", err, txResult.GasUsed) + } + + msgResponses := make([]*codectypes.Any, 0, len(txResult.Resp)) + // pack the messages into Any + for _, msg := range txResult.Resp { + anyMsg, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return nil, status.Errorf(codes.Unknown, "failed to pack message response: %v", err) + } + msgResponses = append(msgResponses, anyMsg) + } + + return &txtypes.SimulateResponse{ + GasInfo: &sdk.GasInfo{ + GasUsed: txResult.GasUsed, + GasWanted: txResult.GasWanted, + }, + Result: &sdk.Result{ + MsgResponses: msgResponses, + }, + }, nil +} + +// TxDecode implements tx.ServiceServer. +func (t txServer[T]) TxDecode(context.Context, *txtypes.TxDecodeRequest) (*txtypes.TxDecodeResponse, error) { + panic("unimplemented") +} + +// TxDecodeAmino implements tx.ServiceServer. +func (t txServer[T]) TxDecodeAmino(context.Context, *txtypes.TxDecodeAminoRequest) (*txtypes.TxDecodeAminoResponse, error) { + panic("unimplemented") +} + +// TxEncode implements tx.ServiceServer. +func (t txServer[T]) TxEncode(context.Context, *txtypes.TxEncodeRequest) (*txtypes.TxEncodeResponse, error) { + panic("unimplemented") +} + +// TxEncodeAmino implements tx.ServiceServer. +func (t txServer[T]) TxEncodeAmino(context.Context, *txtypes.TxEncodeAminoRequest) (*txtypes.TxEncodeAminoResponse, error) { + panic("unimplemented") +} + +var _ txtypes.ServiceServer = txServer[transaction.Tx]{} diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index 382c5675155d..95338cb2c2a2 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -46,6 +46,7 @@ require ( cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000 cosmossdk.io/x/accounts/defaults/lockup v0.0.0-00010101000000-000000000000 cosmossdk.io/x/accounts/defaults/multisig v0.0.0-00010101000000-000000000000 + google.golang.org/grpc v1.68.0 ) require ( @@ -238,7 +239,6 @@ require ( google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.68.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect diff --git a/simapp/v2/simdv2/cmd/commands.go b/simapp/v2/simdv2/cmd/commands.go index 408e7e2cfe25..565292718731 100644 --- a/simapp/v2/simdv2/cmd/commands.go +++ b/simapp/v2/simdv2/cmd/commands.go @@ -130,7 +130,9 @@ func InitRootCmd[T transaction.Tx]( simApp.QueryHandlers(), simApp.Query, []func(*grpc.Server) error{ - deps.ConsensusServer.Consensus.GRPCServiceRegistrar(deps.ClientContext.Client, deps.ClientContext.ConsensusAddressCodec), + deps.ConsensusServer.Consensus.GRPCServiceRegistrar( + deps.ClientContext, + ), }, deps.GlobalConfig, )