Skip to content

Commit

Permalink
Fix from code review
Browse files Browse the repository at this point in the history
  • Loading branch information
mattverse committed Sep 6, 2022
1 parent d50c065 commit af42da8
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 90 deletions.
11 changes: 5 additions & 6 deletions x/wasm/keeper/query_plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
proto "github.com/gogo/protobuf/proto"
abci "github.com/tendermint/tendermint/abci/types"

channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types"
Expand Down Expand Up @@ -275,7 +274,7 @@ func IBCQuerier(wasm contractMetaDataSource, channelKeeper types.ChannelKeeper)

func StargateQuerier(queryRouter GRPCQueryRouter, codec codec.Codec) func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) {
return func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) {
protoResponse, whitelisted := StargateWhitelist.Load(request.Path)
protoResponse, whitelisted := AcceptList.Load(request.Path)
if !whitelisted {
return nil, wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("'%s' path is not allowed from the contract", request.Path)}
}
Expand Down Expand Up @@ -548,20 +547,20 @@ func ConvertSdkCoinToWasmCoin(coin sdk.Coin) wasmvmtypes.Coin {
// ConvertProtoToJSONMarshal unmarshals the given bytes into a proto message and then marshals it to json.
// This is done so that clients calling stargate queries do not need to define their own proto unmarshalers,
// being able to use response directly by json marshalling, which is supported in cosmwasm.
func ConvertProtoToJSONMarshal(protoResponse interface{}, bz []byte, codec codec.Codec) ([]byte, error) {
func ConvertProtoToJSONMarshal(protoResponse interface{}, bz []byte, cdc codec.Codec) ([]byte, error) {
// all values are proto message
message, ok := protoResponse.(proto.Message)
message, ok := protoResponse.(codec.ProtoMarshaler)
if !ok {
return nil, wasmvmtypes.Unknown{}
}

// unmarshal binary into stargate response data structure
err := proto.Unmarshal(bz, message)
err := cdc.Unmarshal(bz, message)
if err != nil {
return nil, wasmvmtypes.Unknown{}
}

bz, err = codec.MarshalJSON(message)
bz, err = cdc.MarshalJSON(message)
if err != nil {
return nil, wasmvmtypes.Unknown{}
}
Expand Down
71 changes: 5 additions & 66 deletions x/wasm/keeper/query_plugins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,15 +588,14 @@ func TestConvertProtoToJSONMarshal(t *testing.T) {
// check response by json marshalling proto response into json response manually
jsonMarshalExpectedResponse, err := wasmApp.AppCodec().MarshalJSON(tc.expectedProtoResponse)
require.NoError(t, err)
require.Equal(t, jsonMarshalledResponse, jsonMarshalExpectedResponse)
require.JSONEq(t, string(jsonMarshalledResponse), string(jsonMarshalExpectedResponse))
})
}
}

// TestDeterministicJsonMarshal tests that we get deterministic JSON marshalled response upon
// proto struct update in the state machine.
func TestDeterministicJsonMarshal(t *testing.T) {

testCases := []struct {
name string
originalResponse string
Expand All @@ -605,50 +604,6 @@ func TestDeterministicJsonMarshal(t *testing.T) {
responseProtoStruct interface{}
expectedProto func() proto.Message
}{

/**
* Origin Response
* balances:<denom:"bar" amount:"30" > pagination:<next_key:"foo" >
* "0a090a036261721202333012050a03666f6f"
*
* New Version Response
* The binary built from the proto response with additional field address
* balances:<denom:"bar" amount:"30" > pagination:<next_key:"foo" > address:"cosmos1j6j5tsquq2jlw2af7l3xekyaq7zg4l8jsufu78"
* "0a090a036261721202333012050a03666f6f1a2d636f736d6f73316a366a357473717571326a6c77326166376c3378656b796171377a67346c386a737566753738"
// Origin proto
message QueryAllBalancesResponse {
// balances is the balances of all the coins.
repeated cosmos.base.v1beta1.Coin balances = 1
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// Updated proto
message QueryAllBalancesResponse {
// balances is the balances of all the coins.
repeated cosmos.base.v1beta1.Coin balances = 1
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
// address is the address to query all balances for.
string address = 3;
}
*/
{
"Query All Balances",
"0a090a036261721202333012050a03666f6f",
"0a090a036261721202333012050a03666f6f1a2d636f736d6f73316a366a357473717571326a6c77326166376c3378656b796171377a67346c386a737566753738",
"/cosmos.bank.v1beta1.Query/AllBalances",
&banktypes.QueryAllBalancesResponse{},
func() proto.Message {
return &banktypes.QueryAllBalancesResponse{
Balances: sdk.NewCoins(sdk.NewCoin("bar", sdk.NewInt(30))),
Pagination: &query.PageResponse{
NextKey: []byte("foo"),
},
}
},
},
/**
*
* Origin Response
Expand Down Expand Up @@ -690,38 +645,22 @@ func TestDeterministicJsonMarshal(t *testing.T) {

for _, tc := range testCases {
t.Run(fmt.Sprintf("Case %s", tc.name), func(t *testing.T) {
// set up app for testing
wasmApp := app.SetupWithEmptyStore(t)
// wasmApp := app.SetupWithEmptyStore(t)

// set up whitelist manually for testing
protoResponse, ok := tc.responseProtoStruct.(proto.Message)
require.True(t, ok)
keeper.StargateWhitelist.Store(tc.queryPath, protoResponse)

// decode original response
originVersionBz, err := hex.DecodeString(tc.originalResponse)
require.NoError(t, err)

// use proto response struct by loading from whitelist
loadedResponseStruct, ok := keeper.StargateWhitelist.Load(tc.queryPath)
require.True(t, ok)
protoResponse, ok = loadedResponseStruct.(proto.Message)

jsonMarshalledOriginalBz, err := keeper.ConvertProtoToJSONMarshal(protoResponse, originVersionBz, wasmApp.AppCodec())
jsonMarshalledOriginalBz, err := keeper.ConvertProtoToJSONMarshal(tc.responseProtoStruct, originVersionBz, wasmApp.AppCodec())
require.NoError(t, err)

wasmApp.AppCodec().MustUnmarshalJSON(jsonMarshalledOriginalBz, protoResponse)

newVersionBz, err := hex.DecodeString(tc.updatedResponse)
require.NoError(t, err)
jsonMarshalledUpdatedBz, err := keeper.ConvertProtoToJSONMarshal(protoResponse, newVersionBz, wasmApp.AppCodec())
jsonMarshalledUpdatedBz, err := keeper.ConvertProtoToJSONMarshal(tc.responseProtoStruct, newVersionBz, wasmApp.AppCodec())
require.NoError(t, err)

// json marshalled bytes should be the same since we use the same proto sturct for unmarshalling
// json marshalled bytes should be the same since we use the same proto struct for unmarshalling
require.Equal(t, jsonMarshalledOriginalBz, jsonMarshalledUpdatedBz)

// raw build should also make same result
// raw build also make same result
jsonMarshalExpectedResponse, err := wasmApp.AppCodec().MarshalJSON(tc.expectedProto())
require.NoError(t, err)
require.Equal(t, jsonMarshalledUpdatedBz, jsonMarshalExpectedResponse)
Expand Down
18 changes: 0 additions & 18 deletions x/wasm/keeper/stargate_bindings.go

This file was deleted.

18 changes: 18 additions & 0 deletions x/wasm/keeper/stargate_whitelist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package keeper

import (
"sync"
)

// AcceptList keeps whitelist and its deterministic
// response binding for stargate queries.
//
// The query can be multi-thread, so we have to use
// thread safe sync.Map.
var AcceptList sync.Map

// Define AcceptList here as maps using 'AcceptList'
// e.x) AcceptList.Store("/cosmos.auth.v1beta1.Query/Account", &authtypes.QueryAccountResponse{})
func init() {

}

0 comments on commit af42da8

Please sign in to comment.