Skip to content

Commit

Permalink
test(server/v2/cometbft): Add Consensus query p2p, app, grpc (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
hieuvubk authored Dec 5, 2024
1 parent 3727f23 commit 9f7f17b
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 9 deletions.
195 changes: 188 additions & 7 deletions server/v2/cometbft/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"io"
"reflect"
"strings"
"sync"
"testing"
Expand All @@ -15,6 +16,7 @@ import (
abciproto "github.com/cometbft/cometbft/api/cometbft/abci/v1"
v1 "github.com/cometbft/cometbft/api/cometbft/types/v1"
"github.com/cosmos/gogoproto/proto"
gogoproto "github.com/cosmos/gogoproto/proto"
gogotypes "github.com/cosmos/gogoproto/types"
"github.com/stretchr/testify/require"

Expand All @@ -33,6 +35,9 @@ import (
"cosmossdk.io/server/v2/stf/branch"
"cosmossdk.io/server/v2/stf/mock"
consensustypes "cosmossdk.io/x/consensus/types"

"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
)

var (
Expand All @@ -53,7 +58,9 @@ var (
Msg: &gogotypes.BoolValue{Value: true},
GasLimit: 0,
}
actorName = []byte("cookies")
actorName = []byte("cookies")
testAcc = sdk.AccAddress([]byte("addr1_______________"))
versionStr = "0.0.0"
)

func getQueryRouterBuilder[T any, PT interface {
Expand Down Expand Up @@ -583,11 +590,7 @@ func TestConsensus_Info(t *testing.T) {
require.Equal(t, res.LastBlockHeight, int64(1))
}

// TODO:
// - GRPC request
// - app request
// - p2p request
func TestConsensus_Query(t *testing.T) {
func TestConsensus_QueryStore(t *testing.T) {
c := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{})

// Write data to state storage
Expand Down Expand Up @@ -648,11 +651,149 @@ func TestConsensus_Query(t *testing.T) {
require.Equal(t, res.Value, []byte(nil))
}

func TestConsensus_GRPCQuery(t *testing.T) {
c := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{})

_, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{
Time: time.Now(),
ChainId: "test",
InitialHeight: 1,
})
require.NoError(t, err)

_, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{
Time: time.Now(),
Height: 1,
Txs: [][]byte{mockTx.Bytes()},
Hash: emptyHash[:],
})
require.NoError(t, err)

// empty request
res, err := c.Query(context.Background(), &abciproto.QueryRequest{})
require.NoError(t, err)
require.Equal(t, res.Code, uint32(1))
require.Contains(t, res.Log, "no query path provided")

// query request not exist in handler map
invalidReq := testdata.EchoRequest{
Message: "echo",
}
invalidReqBz, err := invalidReq.Marshal()
require.NoError(t, err)
invalidQuery := abci.QueryRequest{
Data: invalidReqBz,
Path: "testpb.EchoRequest",
}
invalidRes, err := c.Query(context.TODO(), &invalidQuery)
require.Error(t, err)
require.Nil(t, invalidRes)
require.Contains(t, err.Error(), "no query handler found")

// Valid query
req := testdata.SayHelloRequest{Name: "foo"}
reqBz, err := req.Marshal()
require.NoError(t, err)
reqQuery := abci.QueryRequest{
Data: reqBz,
Path: "testpb.SayHelloRequest",
}

resQuery, err := c.Query(context.TODO(), &reqQuery)
require.NoError(t, err)
require.Equal(t, abci.CodeTypeOK, resQuery.Code, resQuery)

var response testdata.SayHelloResponse
require.NoError(t, response.Unmarshal(resQuery.Value))
require.Equal(t, "Hello foo!", response.Greeting)
}

func TestConsensus_P2PQuery(t *testing.T) {
c := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{})

_, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{
Time: time.Now(),
ChainId: "test",
InitialHeight: 1,
})
require.NoError(t, err)

_, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{
Time: time.Now(),
Height: 1,
Txs: [][]byte{mockTx.Bytes()},
Hash: emptyHash[:],
})
require.NoError(t, err)

// empty request
res, err := c.Query(context.Background(), &abciproto.QueryRequest{})
require.NoError(t, err)
require.Equal(t, res.Code, uint32(1))
require.Contains(t, res.Log, "no query path provided")

addrQuery := abci.QueryRequest{
Path: "/p2p/filter/addr/1.1.1.1:8000",
}
res, err = c.Query(context.TODO(), &addrQuery)
require.NoError(t, err)
require.Equal(t, uint32(3), res.Code)

idQuery := abci.QueryRequest{
Path: "/p2p/filter/id/testid",
}
res, err = c.Query(context.TODO(), &idQuery)
require.NoError(t, err)
require.Equal(t, uint32(4), res.Code)
}

func TestConsensus_AppQuery(t *testing.T) {
c := setUpConsensus(t, 100_000, cometmock.MockMempool[mock.Tx]{})

_, err := c.InitChain(context.Background(), &abciproto.InitChainRequest{
Time: time.Now(),
ChainId: "test",
InitialHeight: 1,
})
require.NoError(t, err)

_, err = c.FinalizeBlock(context.Background(), &abciproto.FinalizeBlockRequest{
Time: time.Now(),
Height: 1,
Txs: [][]byte{mockTx.Bytes()},
Hash: emptyHash[:],
})
require.NoError(t, err)

tx := mock.Tx{
Sender: testAcc,
Msg: &gogotypes.BoolValue{Value: true},
GasLimit: 1000,
}
txBytes := tx.Bytes()

// simulate by calling Query with encoded tx
query := abci.QueryRequest{
Path: "/app/simulate",
Data: txBytes,
}
queryResult, err := c.Query(context.TODO(), &query)
require.NoError(t, err)
require.True(t, queryResult.IsOK(), queryResult.Log)

// Query app version
res, err := c.Query(context.TODO(), &abci.QueryRequest{Path: "app/version"})
require.NoError(t, err)
require.True(t, res.IsOK())
require.Equal(t, versionStr, string(res.Value))
}

func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock.Tx]) *consensus[mock.Tx] {
t.Helper()

queryHandler := make(map[string]appmodulev2.Handler)
msgRouterBuilder := getMsgRouterBuilder(t, func(ctx context.Context, msg *gogotypes.BoolValue) (*gogotypes.BoolValue, error) {
return nil, nil
return msg, nil
})

queryRouterBuilder := getQueryRouterBuilder(t, func(ctx context.Context, q *consensustypes.QueryParamsRequest) (*consensustypes.QueryParamsResponse, error) {
Expand All @@ -669,6 +810,32 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock.
}, nil
})

helloFooHandler := func(ctx context.Context, msg transaction.Msg) (msgResp transaction.Msg, err error) {
typedReq := msg.(*testdata.SayHelloRequest)
handler := testdata.QueryImpl{}
typedResp, err := handler.SayHello(ctx, typedReq)
if err != nil {
return nil, err
}

return typedResp, nil
}

queryRouterBuilder.RegisterHandler(
proto.MessageName(&testdata.SayHelloRequest{}),
helloFooHandler,
)

queryHandler[proto.MessageName(&testdata.SayHelloRequest{})] = appmodulev2.Handler{
Func: helloFooHandler,
MakeMsg: func() transaction.Msg {
return reflect.New(gogoproto.MessageType(proto.MessageName(&testdata.SayHelloRequest{})).Elem()).Interface().(transaction.Msg)
},
MakeMsgResp: func() transaction.Msg {
return reflect.New(gogoproto.MessageType(proto.MessageName(&testdata.SayHelloResponse{})).Elem()).Interface().(transaction.Msg)
},
}

s, err := stf.New(
log.NewNopLogger().With("module", "stf"),
msgRouterBuilder,
Expand Down Expand Up @@ -709,6 +876,16 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock.
nil,
)

addrPeerFilter := func(info string) (*abci.QueryResponse, error) {
require.Equal(t, "1.1.1.1:8000", info)
return &abci.QueryResponse{Code: uint32(3)}, nil
}

idPeerFilter := func(id string) (*abci.QueryResponse, error) {
require.Equal(t, "testid", id)
return &abci.QueryResponse{Code: uint32(4)}, nil
}

return &consensus[mock.Tx]{
logger: log.NewNopLogger(),
appName: "testing-app",
Expand All @@ -719,6 +896,10 @@ func setUpConsensus(t *testing.T, gasLimit uint64, mempool mempool.Mempool[mock.
txCodec: mock.TxCodec{},
chainID: "test",
getProtoRegistry: sync.OnceValues(proto.MergedRegistry),
queryHandlersMap: queryHandler,
addrPeerFilter: addrPeerFilter,
idPeerFilter: idPeerFilter,
version: versionStr,
}
}

Expand Down
8 changes: 6 additions & 2 deletions server/v2/cometbft/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,19 @@ func intoABCISimulationResponse(txRes server.TxResult, indexSet map[string]struc
msgResponses[i] = anyMsg
}

errMsg := ""
if txRes.Error != nil {
errMsg = txRes.Error.Error()
}

res := &sdk.SimulationResponse{
GasInfo: sdk.GasInfo{
GasWanted: txRes.GasWanted,
GasUsed: txRes.GasUsed,
},
Result: &sdk.Result{
Data: []byte{},
Log: txRes.Error.Error(),
Log: errMsg,
Events: abciEvents,
MsgResponses: msgResponses,
},
Expand Down Expand Up @@ -284,7 +289,6 @@ func gRPCErrorToSDKError(err error) *abci.QueryResponse {
res.Log = err.Error()
}
return res

}

status, ok := grpcstatus.FromError(err)
Expand Down

0 comments on commit 9f7f17b

Please sign in to comment.