Skip to content

Commit

Permalink
Add CodeInfo rpc query (#1943)
Browse files Browse the repository at this point in the history
* Add CodeInfo rpc query

* Fix typos

* Add QueryCodeInfoResponse type

* Inline fields in QueryCodeInfoResponse

* Fix comments
  • Loading branch information
pinosu committed Sep 11, 2024
1 parent 2345840 commit 2e54595
Show file tree
Hide file tree
Showing 8 changed files with 915 additions and 142 deletions.
1 change: 0 additions & 1 deletion benchmarks/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import (
)

func setup(db dbm.DB, withGenesis bool) (*app.WasmApp, app.GenesisState) {

logLevel := log.LevelOption(zerolog.InfoLevel)

wasmApp := app.NewWasmApp(log.NewLogger(os.Stdout, logLevel), db, nil, true, simtestutil.EmptyAppOptions{}, nil)
Expand Down
42 changes: 39 additions & 3 deletions docs/proto/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
- [QueryAllContractStateResponse](#cosmwasm.wasm.v1.QueryAllContractStateResponse)
- [QueryBuildAddressRequest](#cosmwasm.wasm.v1.QueryBuildAddressRequest)
- [QueryBuildAddressResponse](#cosmwasm.wasm.v1.QueryBuildAddressResponse)
- [QueryCodeInfoRequest](#cosmwasm.wasm.v1.QueryCodeInfoRequest)
- [QueryCodeInfoResponse](#cosmwasm.wasm.v1.QueryCodeInfoResponse)
- [QueryCodeRequest](#cosmwasm.wasm.v1.QueryCodeRequest)
- [QueryCodeResponse](#cosmwasm.wasm.v1.QueryCodeResponse)
- [QueryCodesRequest](#cosmwasm.wasm.v1.QueryCodesRequest)
Expand Down Expand Up @@ -1066,6 +1068,39 @@ method.



<a name="cosmwasm.wasm.v1.QueryCodeInfoRequest"></a>

### QueryCodeInfoRequest
QueryCodeInfoRequest is the request type for the Query/CodeInfo RPC method


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `code_id` | [uint64](#uint64) | | grpc-gateway_out does not support Go style CodeID |






<a name="cosmwasm.wasm.v1.QueryCodeInfoResponse"></a>

### QueryCodeInfoResponse
QueryCodeInfoResponse is the response type for the Query/CodeInfo RPC method


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `code_id` | [uint64](#uint64) | | |
| `creator` | [string](#string) | | |
| `checksum` | [bytes](#bytes) | | |
| `instantiate_permission` | [AccessConfig](#cosmwasm.wasm.v1.AccessConfig) | | |






<a name="cosmwasm.wasm.v1.QueryCodeRequest"></a>

### QueryCodeRequest
Expand All @@ -1074,7 +1109,7 @@ QueryCodeRequest is the request type for the Query/Code RPC method

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `code_id` | [uint64](#uint64) | | grpc-gateway_out does not support Go style CodID |
| `code_id` | [uint64](#uint64) | | grpc-gateway_out does not support Go style CodeID |



Expand Down Expand Up @@ -1204,7 +1239,7 @@ RPC method

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `code_id` | [uint64](#uint64) | | grpc-gateway_out does not support Go style CodID |
| `code_id` | [uint64](#uint64) | | grpc-gateway_out does not support Go style CodeID |
| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. |


Expand Down Expand Up @@ -1406,8 +1441,9 @@ Query provides defines the gRPC querier service
| `AllContractState` | [QueryAllContractStateRequest](#cosmwasm.wasm.v1.QueryAllContractStateRequest) | [QueryAllContractStateResponse](#cosmwasm.wasm.v1.QueryAllContractStateResponse) | AllContractState gets all raw store data for a single contract | GET|/cosmwasm/wasm/v1/contract/{address}/state|
| `RawContractState` | [QueryRawContractStateRequest](#cosmwasm.wasm.v1.QueryRawContractStateRequest) | [QueryRawContractStateResponse](#cosmwasm.wasm.v1.QueryRawContractStateResponse) | RawContractState gets single key from the raw store data of a contract | GET|/cosmwasm/wasm/v1/contract/{address}/raw/{query_data}|
| `SmartContractState` | [QuerySmartContractStateRequest](#cosmwasm.wasm.v1.QuerySmartContractStateRequest) | [QuerySmartContractStateResponse](#cosmwasm.wasm.v1.QuerySmartContractStateResponse) | SmartContractState get smart query result from the contract | GET|/cosmwasm/wasm/v1/contract/{address}/smart/{query_data}|
| `Code` | [QueryCodeRequest](#cosmwasm.wasm.v1.QueryCodeRequest) | [QueryCodeResponse](#cosmwasm.wasm.v1.QueryCodeResponse) | Code gets the binary code and metadata for a singe wasm code | GET|/cosmwasm/wasm/v1/code/{code_id}|
| `Code` | [QueryCodeRequest](#cosmwasm.wasm.v1.QueryCodeRequest) | [QueryCodeResponse](#cosmwasm.wasm.v1.QueryCodeResponse) | Code gets the binary code and metadata for a single wasm code | GET|/cosmwasm/wasm/v1/code/{code_id}|
| `Codes` | [QueryCodesRequest](#cosmwasm.wasm.v1.QueryCodesRequest) | [QueryCodesResponse](#cosmwasm.wasm.v1.QueryCodesResponse) | Codes gets the metadata for all stored wasm codes | GET|/cosmwasm/wasm/v1/code|
| `CodeInfo` | [QueryCodeInfoRequest](#cosmwasm.wasm.v1.QueryCodeInfoRequest) | [QueryCodeInfoResponse](#cosmwasm.wasm.v1.QueryCodeInfoResponse) | CodeInfo gets the metadata for a single wasm code | GET|/cosmwasm/wasm/v1/code-info/{code_id}|
| `PinnedCodes` | [QueryPinnedCodesRequest](#cosmwasm.wasm.v1.QueryPinnedCodesRequest) | [QueryPinnedCodesResponse](#cosmwasm.wasm.v1.QueryPinnedCodesResponse) | PinnedCodes gets the pinned code ids | GET|/cosmwasm/wasm/v1/codes/pinned|
| `Params` | [QueryParamsRequest](#cosmwasm.wasm.v1.QueryParamsRequest) | [QueryParamsResponse](#cosmwasm.wasm.v1.QueryParamsResponse) | Params gets the module params | GET|/cosmwasm/wasm/v1/codes/params|
| `ContractsByCreator` | [QueryContractsByCreatorRequest](#cosmwasm.wasm.v1.QueryContractsByCreatorRequest) | [QueryContractsByCreatorResponse](#cosmwasm.wasm.v1.QueryContractsByCreatorResponse) | ContractsByCreator gets the contracts by creator | GET|/cosmwasm/wasm/v1/contracts/creator/{creator_address}|
Expand Down
29 changes: 26 additions & 3 deletions proto/cosmwasm/wasm/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ service Query {
option (google.api.http).get =
"/cosmwasm/wasm/v1/contract/{address}/smart/{query_data}";
}
// Code gets the binary code and metadata for a singe wasm code
// Code gets the binary code and metadata for a single wasm code
rpc Code(QueryCodeRequest) returns (QueryCodeResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/cosmwasm/wasm/v1/code/{code_id}";
Expand All @@ -64,6 +64,12 @@ service Query {
option (google.api.http).get = "/cosmwasm/wasm/v1/code";
}

// CodeInfo gets the metadata for a single wasm code
rpc CodeInfo(QueryCodeInfoRequest) returns (QueryCodeInfoResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/cosmwasm/wasm/v1/code-info/{code_id}";
}

// PinnedCodes gets the pinned code ids
rpc PinnedCodes(QueryPinnedCodesRequest) returns (QueryPinnedCodesResponse) {
option (cosmos.query.v1.module_query_safe) = true;
Expand Down Expand Up @@ -134,7 +140,7 @@ message QueryContractHistoryResponse {
// QueryContractsByCodeRequest is the request type for the Query/ContractsByCode
// RPC method
message QueryContractsByCodeRequest {
uint64 code_id = 1; // grpc-gateway_out does not support Go style CodID
uint64 code_id = 1; // grpc-gateway_out does not support Go style CodeID
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
Expand Down Expand Up @@ -207,7 +213,24 @@ message QuerySmartContractStateResponse {

// QueryCodeRequest is the request type for the Query/Code RPC method
message QueryCodeRequest {
uint64 code_id = 1; // grpc-gateway_out does not support Go style CodID
uint64 code_id = 1; // grpc-gateway_out does not support Go style CodeID
}

// QueryCodeInfoRequest is the request type for the Query/CodeInfo RPC method
message QueryCodeInfoRequest {
uint64 code_id = 1; // grpc-gateway_out does not support Go style CodeID
}

// QueryCodeInfoResponse is the response type for the Query/CodeInfo RPC method
message QueryCodeInfoResponse {
option (gogoproto.equal) = true;

uint64 code_id = 1 [ (gogoproto.customname) = "CodeID" ];
string creator = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
bytes checksum = 3 [ (gogoproto.casttype) =
"github.com/cometbft/cometbft/libs/bytes.HexBytes" ];
AccessConfig instantiate_permission = 4
[ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ];
}

// CodeInfoResponse contains code meta data from CodeInfo
Expand Down
9 changes: 3 additions & 6 deletions x/wasm/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,20 +252,17 @@ func GetCmdQueryCodeInfo() *cobra.Command {
}

queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Code(
res, err := queryClient.CodeInfo(
context.Background(),
&types.QueryCodeRequest{
&types.QueryCodeInfoRequest{
CodeId: codeID,
},
)
if err != nil {
return err
}
if res.CodeInfoResponse == nil {
return fmt.Errorf("contract not found")
}

return clientCtx.PrintProto(res.CodeInfoResponse)
return clientCtx.PrintProto(res)
},
SilenceUsage: true,
}
Expand Down
47 changes: 37 additions & 10 deletions x/wasm/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,25 @@ func (q GrpcQuerier) Codes(c context.Context, req *types.QueryCodesRequest) (*ty
return &types.QueryCodesResponse{CodeInfos: r, Pagination: pageRes}, nil
}

func (q GrpcQuerier) CodeInfo(c context.Context, req *types.QueryCodeInfoRequest) (*types.QueryCodeInfoResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if req.CodeId == 0 {
return nil, errorsmod.Wrap(types.ErrInvalid, "code id")
}
info := queryCodeInfo(sdk.UnwrapSDKContext(c), req.CodeId, q.keeper)
if info == nil {
return nil, types.ErrNoSuchCodeFn(req.CodeId).Wrapf("code id %d", req.CodeId)
}
return &types.QueryCodeInfoResponse{
CodeID: info.CodeID,
Creator: info.Creator,
Checksum: info.DataHash,
InstantiatePermission: info.InstantiatePermission,
}, nil
}

func queryContractInfo(ctx sdk.Context, addr sdk.AccAddress, keeper types.ViewKeeper) (*types.QueryContractInfoResponse, error) {
info := keeper.GetContractInfo(ctx, addr)
if info == nil {
Expand All @@ -298,27 +317,35 @@ func queryContractInfo(ctx sdk.Context, addr sdk.AccAddress, keeper types.ViewKe
}

func queryCode(ctx sdk.Context, codeID uint64, keeper types.ViewKeeper) (*types.QueryCodeResponse, error) {
if codeID == 0 {
info := queryCodeInfo(ctx, codeID, keeper)
if info == nil {
// nil, nil leads to 404 in rest handler
return nil, nil
}

code, err := keeper.GetByteCode(ctx, codeID)
if err != nil {
return nil, errorsmod.Wrap(err, "loading wasm code")
}

return &types.QueryCodeResponse{CodeInfoResponse: info, Data: code}, nil
}

func queryCodeInfo(ctx sdk.Context, codeID uint64, keeper types.ViewKeeper) *types.CodeInfoResponse {
if codeID == 0 {
return nil
}
res := keeper.GetCodeInfo(ctx, codeID)
if res == nil {
// nil, nil leads to 404 in rest handler
return nil, nil
return nil
}
info := types.CodeInfoResponse{
CodeID: codeID,
Creator: res.Creator,
DataHash: res.CodeHash,
InstantiatePermission: res.InstantiateConfig,
}

code, err := keeper.GetByteCode(ctx, codeID)
if err != nil {
return nil, errorsmod.Wrap(err, "loading wasm code")
}

return &types.QueryCodeResponse{CodeInfoResponse: &info, Data: code}, nil
return &info
}

func (q GrpcQuerier) PinnedCodes(c context.Context, req *types.QueryPinnedCodesRequest) (*types.QueryPinnedCodesResponse, error) {
Expand Down
52 changes: 52 additions & 0 deletions x/wasm/keeper/querier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,58 @@ func TestQueryCodeInfo(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
keeper := keepers.WasmKeeper

anyAddress, err := sdk.AccAddressFromBech32("cosmos100dejzacpanrldpjjwksjm62shqhyss44jf5xz")
require.NoError(t, err)
specs := map[string]struct {
codeID uint64
accessConfig types.AccessConfig
}{
"everybody": {
codeID: 1,
accessConfig: types.AllowEverybody,
},
"nobody": {
codeID: 10,
accessConfig: types.AllowNobody,
},
"with_address": {
codeID: 20,
accessConfig: types.AccessTypeAnyOfAddresses.With(anyAddress),
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
codeInfo := types.CodeInfoFixture(types.WithSHA256CodeHash(wasmCode))
codeInfo.InstantiateConfig = spec.accessConfig
require.NoError(t, keeper.importCode(ctx, spec.codeID,
codeInfo,
wasmCode),
)

q := Querier(keeper)
got, err := q.CodeInfo(ctx, &types.QueryCodeInfoRequest{
CodeId: spec.codeID,
})
require.NoError(t, err)
expectedResponse := &types.QueryCodeInfoResponse{
CodeID: spec.codeID,
Creator: codeInfo.Creator,
Checksum: codeInfo.CodeHash,
InstantiatePermission: spec.accessConfig,
}
require.NotNil(t, got)
require.EqualValues(t, expectedResponse, got)
})
}
}

func TestQueryCode(t *testing.T) {
wasmCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)

ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
keeper := keepers.WasmKeeper

anyAddress, err := sdk.AccAddressFromBech32("cosmos100dejzacpanrldpjjwksjm62shqhyss44jf5xz")
require.NoError(t, err)
specs := map[string]struct {
Expand Down
Loading

0 comments on commit 2e54595

Please sign in to comment.