Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add consumer chain query #2179

Merged
merged 12 commits into from
Aug 29, 2024
21 changes: 21 additions & 0 deletions proto/interchain_security/ccv/provider/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,14 @@ service Query {
option (google.api.http).get =
"/interchain_security/ccv/provider/consumer_id/{client_id}";
}

// QueryConsumerChain returns the consumer chain
// associated with the provided consumer id
rpc QueryConsumerChain(QueryConsumerChainRequest)
returns (QueryConsumerChainResponse) {
option (google.api.http).get =
"/interchain_security/ccv/provider/consumer_chain/{consumer_id}";
}
}

message QueryConsumerGenesisRequest {
Expand Down Expand Up @@ -431,3 +439,16 @@ message QueryConsumerIdFromClientIdResponse {
// the consumer id of the chain associated with this client id
string consumer_id = 1;
}

message QueryConsumerChainRequest {
string consumer_id = 1;
}

message QueryConsumerChainResponse {
string chain_id = 1;
string owner_address = 2;
string phase = 3;
ConsumerMetadata metadata = 4 [ (gogoproto.nullable) = false ];
ConsumerInitializationParameters init_params = 5;
PowerShapingParameters power_shaping_params = 6;
}
46 changes: 46 additions & 0 deletions x/ccv/provider/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,3 +580,49 @@ func (k Keeper) QueryConsumerIdFromClientId(goCtx context.Context, req *types.Qu

return &types.QueryConsumerIdFromClientIdResponse{ConsumerId: consumerId}, nil
}

// QueryConsumerChain returns the consumer chain associated with the consumer id
func (k Keeper) QueryConsumerChain(goCtx context.Context, req *types.QueryConsumerChainRequest) (*types.QueryConsumerChainResponse, error) {
if req == nil {
return nil, status.Errorf(codes.InvalidArgument, "empty request")
}

consumerId := req.ConsumerId
if err := types.ValidateConsumerId(consumerId); err != nil {
return nil, status.Error(codes.InvalidArgument, errorsmod.Wrap(types.ErrInvalidConsumerId, consumerId).Error())
}
ctx := sdk.UnwrapSDKContext(goCtx)

chainId, err := k.GetConsumerChainId(ctx, consumerId)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "cannot retrieve chain id for consumer id: %s", consumerId)
}

ownerAddress, err := k.GetConsumerOwnerAddress(ctx, consumerId)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "cannot retrieve owner address for consumer id: %s", consumerId)
}

phase := k.GetConsumerPhase(ctx, consumerId)
if phase == types.ConsumerPhase_CONSUMER_PHASE_UNSPECIFIED {
return nil, status.Errorf(codes.InvalidArgument, "cannot retrieve phase for consumer id: %s", consumerId)
}

metadata, err := k.GetConsumerMetadata(ctx, consumerId)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "cannot retrieve metadata for consumer id: %s", consumerId)
}

// neither the init nor the power shaping params are mandatory for consumers
initParams, _ := k.GetConsumerInitializationParameters(ctx, consumerId)
powerParams, _ := k.GetConsumerPowerShapingParameters(ctx, consumerId)

return &types.QueryConsumerChainResponse{
ChainId: chainId,
OwnerAddress: ownerAddress,
Phase: phase.String(),
Metadata: metadata,
InitParams: &initParams,
PowerShapingParams: &powerParams,
}, nil
}
79 changes: 70 additions & 9 deletions x/ccv/provider/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,6 @@ func TestQueryConsumerValidators(t *testing.T) {
res, err = pk.QueryConsumerValidators(ctx, &req)
require.NoError(t, err)
require.Equal(t, val1.Commission.Rate, res.Validators[0].ConsumerCommissionRate)

// set consumer to stopped phase
pk.SetConsumerPhase(ctx, consumerId, types.ConsumerPhase_CONSUMER_PHASE_STOPPED)
// expect empty valset
res, err = pk.QueryConsumerValidators(ctx, &req)
require.NoError(t, err)
require.Empty(t, res)
}

func TestQueryConsumerChainsValidatorHasToValidate(t *testing.T) {
Expand Down Expand Up @@ -444,8 +437,6 @@ func TestGetConsumerChain(t *testing.T) {
Top_N: topN,
ValidatorSetCap: validatorSetCaps[i],
ValidatorsPowerCap: validatorPowerCaps[i],
AllowInactiveVals: allowInactiveVals[i],
MinStake: minStakes[i].Uint64(),
})
pk.SetMinimumPowerInTopN(ctx, consumerID, expectedMinPowerInTopNs[i])
for _, addr := range allowlists[i] {
Expand Down Expand Up @@ -486,6 +477,76 @@ func TestGetConsumerChain(t *testing.T) {
}
}

func TestQueryConsumerChain(t *testing.T) {
providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()

consumerId := "0"
chainId := "consumer-1"

req := types.QueryConsumerChainRequest{
ConsumerId: consumerId,
}

// expect error when consumer isn't associated with a chain id
_, err := providerKeeper.QueryConsumerChain(ctx, &req)
require.Error(t, err)

providerKeeper.SetConsumerChainId(ctx, consumerId, chainId)

// expect error when consumer doesn't have an owner address set
_, err = providerKeeper.QueryConsumerChain(ctx, &req)
require.Error(t, err)

providerKeeper.SetConsumerOwnerAddress(ctx, consumerId, providerKeeper.GetAuthority())

// expect error when consumer doesn't have a valid phase
_, err = providerKeeper.QueryConsumerChain(ctx, &req)
require.Error(t, err)

providerKeeper.SetConsumerPhase(ctx, consumerId, types.ConsumerPhase_CONSUMER_PHASE_REGISTERED)

// expect error when consumer doesn't have metadata
_, err = providerKeeper.QueryConsumerChain(ctx, &req)
require.Error(t, err)

providerKeeper.SetConsumerMetadata(ctx, consumerId, types.ConsumerMetadata{Name: chainId})

expRes := types.QueryConsumerChainResponse{
ChainId: chainId,
OwnerAddress: providerKeeper.GetAuthority(),
Metadata: types.ConsumerMetadata{Name: chainId},
Phase: types.ConsumerPhase_CONSUMER_PHASE_REGISTERED.String(),
InitParams: &types.ConsumerInitializationParameters{},
PowerShapingParams: &types.PowerShapingParameters{},
}

// expect no error when neither the consumer init and power shaping params are set
res, err := providerKeeper.QueryConsumerChain(ctx, &req)
require.NoError(t, err)
require.Equal(t, &expRes, res)

providerKeeper.SetConsumerInitializationParameters(
ctx,
consumerId,
types.ConsumerInitializationParameters{SpawnTime: ctx.BlockTime()},
)

providerKeeper.SetConsumerPowerShapingParameters(
ctx,
consumerId,
types.PowerShapingParameters{Top_N: uint32(50)},
)

expRes.InitParams = &types.ConsumerInitializationParameters{SpawnTime: ctx.BlockTime()}
expRes.PowerShapingParams = &types.PowerShapingParameters{Top_N: uint32(50)}

// expect no error
res, err = providerKeeper.QueryConsumerChain(ctx, &req)
require.NoError(t, err)
require.Equal(t, &expRes, res)
}

func TestQueryConsumerIdFromClientId(t *testing.T) {
providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()
Expand Down
Loading
Loading