Skip to content

Commit

Permalink
init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
insumity committed Oct 29, 2024
1 parent dd09294 commit 81907cb
Show file tree
Hide file tree
Showing 8 changed files with 273 additions and 130 deletions.
5 changes: 5 additions & 0 deletions proto/interchain_security/ccv/provider/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,11 @@ message MsgUpdateConsumer {

// allowlisted reward denoms of the consumer (if provided they overwrite previously set reward denoms)
AllowlistedRewardDenoms allowlisted_reward_denoms = 7;

// (optional) If the consumer chain has NOT yet launched, the chain id can be updated. After a chain has launched
// the chain id CANNOT be updated.
// This field is optional and can remain empty (i.e., `chain_id = ""`) or correspond to chain id the chain already has.
string new_chain_id = 8;
}

// MsgUpdateConsumerResponse defines response type for MsgUpdateConsumer messages
Expand Down
2 changes: 1 addition & 1 deletion x/ccv/provider/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ If one of the fields is missing, it will be set to its zero value.
}

msg, err := types.NewMsgUpdateConsumer(owner, consUpdate.ConsumerId, consUpdate.NewOwnerAddress, consUpdate.Metadata,
consUpdate.InitializationParameters, consUpdate.PowerShapingParameters, consUpdate.AllowlistedRewardDenoms)
consUpdate.InitializationParameters, consUpdate.PowerShapingParameters, consUpdate.AllowlistedRewardDenoms, consUpdate.NewChainId)
if err != nil {
return err
}
Expand Down
10 changes: 10 additions & 0 deletions x/ccv/provider/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,16 @@ func (k msgServer) UpdateConsumer(goCtx context.Context, msg *types.MsgUpdateCon
return &resp, errorsmod.Wrapf(ccvtypes.ErrInvalidConsumerState, "cannot get consumer chain ID: %s", err.Error())
}

if strings.TrimSpace(msg.NewChainId) != "" && msg.NewChainId != chainId {
if k.IsConsumerPrelaunched(ctx, consumerId) {
chainId = msg.NewChainId
k.SetConsumerChainId(ctx, consumerId, chainId)
} else {
// the chain id cannot be updated if the chain is NOT in a prelaunched (i.e., registered or initialized) phase
return &resp, errorsmod.Wrapf(types.ErrInvalidPhase, "cannot update chain id of a non-prelaunched chain: %s", k.GetConsumerPhase(ctx, consumerId))
}
}

// add event attributes
eventAttributes = append(eventAttributes, []sdk.Attribute{
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
Expand Down
51 changes: 50 additions & 1 deletion x/ccv/provider/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,10 @@ func TestUpdateConsumer(t *testing.T) {
require.Error(t, err, "cannot update consumer chain")

// create a chain before updating it
chainId := "chainId-1"
createConsumerResponse, err := msgServer.CreateConsumer(ctx,
&providertypes.MsgCreateConsumer{
Submitter: "submitter", ChainId: "chainId-1",
Submitter: "submitter", ChainId: chainId,
Metadata: providertypes.ConsumerMetadata{
Name: "name",
Description: "description",
Expand All @@ -106,6 +107,21 @@ func TestUpdateConsumer(t *testing.T) {
})
require.Error(t, err, "expected owner address")

// assert that we can change the chain id of a registered chain
expectedChainId := "newChainId-1"
_, err = msgServer.UpdateConsumer(ctx,
&providertypes.MsgUpdateConsumer{
Owner: "submitter", ConsumerId: consumerId,
Metadata: nil,
InitializationParameters: nil,
PowerShapingParameters: nil,
NewChainId: expectedChainId,
})
require.NoError(t, err)
chainId, err = providerKeeper.GetConsumerChainId(ctx, consumerId)
require.NoError(t, err)
require.Equal(t, expectedChainId, chainId)

expectedConsumerMetadata := providertypes.ConsumerMetadata{
Name: "name2",
Description: "description2",
Expand All @@ -117,12 +133,14 @@ func TestUpdateConsumer(t *testing.T) {
expectedPowerShapingParameters := testkeeper.GetTestPowerShapingParameters()

expectedOwnerAddress := "cosmos1dkas8mu4kyhl5jrh4nzvm65qz588hy9qcz08la"
expectedChainId = "updatedChainId-1"
_, err = msgServer.UpdateConsumer(ctx,
&providertypes.MsgUpdateConsumer{
Owner: "submitter", ConsumerId: consumerId, NewOwnerAddress: expectedOwnerAddress,
Metadata: &expectedConsumerMetadata,
InitializationParameters: &expectedInitializationParameters,
PowerShapingParameters: &expectedPowerShapingParameters,
NewChainId: expectedChainId,
})
require.NoError(t, err)

Expand All @@ -146,6 +164,11 @@ func TestUpdateConsumer(t *testing.T) {
require.NoError(t, err)
require.Equal(t, expectedPowerShapingParameters, actualPowerShapingParameters)

// assert that the chain id has been updated
actualChainId, err := providerKeeper.GetConsumerChainId(ctx, consumerId)
require.NoError(t, err)
require.Equal(t, expectedChainId, actualChainId)

// assert phase
phase := providerKeeper.GetConsumerPhase(ctx, consumerId)
require.Equal(t, providertypes.CONSUMER_PHASE_INITIALIZED, phase)
Expand Down Expand Up @@ -191,6 +214,32 @@ func TestUpdateConsumer(t *testing.T) {
})
require.ErrorContains(t, err, "cannot update the initialization parameters of an an already launched chain")

// assert that we CANNOT change the chain id of a launched chain
providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_LAUNCHED)
_, err = msgServer.UpdateConsumer(ctx,
&providertypes.MsgUpdateConsumer{
Owner: expectedOwnerAddress, ConsumerId: consumerId,
Metadata: nil,
InitializationParameters: nil,
PowerShapingParameters: nil,
NewChainId: "newChainId",
})
require.ErrorContains(t, err, "cannot update chain id of a non-prelaunched chain")

// assert that we can use set the chain's current chain id as a `NewChainId` even if the chain has launched
chainId, err = providerKeeper.GetConsumerChainId(ctx, consumerId)
require.NoError(t, err)
providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_LAUNCHED)
_, err = msgServer.UpdateConsumer(ctx,
&providertypes.MsgUpdateConsumer{
Owner: expectedOwnerAddress, ConsumerId: consumerId,
Metadata: nil,
InitializationParameters: nil,
PowerShapingParameters: nil,
NewChainId: chainId,
})
require.NoError(t, err)

// assert that we can update the consumer metadata of a launched chain
providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_LAUNCHED)
expectedConsumerMetadata.Name = "name of a launched chain"
Expand Down
7 changes: 7 additions & 0 deletions x/ccv/provider/keeper/permissionless.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ func (k Keeper) DeleteConsumerPhase(ctx sdk.Context, consumerId string) {
store.Delete(types.ConsumerIdToPhaseKey(consumerId))
}

// IsConsumerPrelaunched checks if a consumer chain is in its prelaunch phase
func (k Keeper) IsConsumerPrelaunched(ctx sdk.Context, consumerId string) bool {
phase := k.GetConsumerPhase(ctx, consumerId)
return phase == types.CONSUMER_PHASE_REGISTERED ||
phase == types.CONSUMER_PHASE_INITIALIZED
}

// IsConsumerActive checks if a consumer chain is either registered, initialized, or launched.
func (k Keeper) IsConsumerActive(ctx sdk.Context, consumerId string) bool {
phase := k.GetConsumerPhase(ctx, consumerId)
Expand Down
8 changes: 7 additions & 1 deletion x/ccv/provider/types/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ func (msg MsgCreateConsumer) ValidateBasic() error {
// NewMsgUpdateConsumer creates a new MsgUpdateConsumer instance
func NewMsgUpdateConsumer(owner, consumerId, ownerAddress string, metadata *ConsumerMetadata,
initializationParameters *ConsumerInitializationParameters, powerShapingParameters *PowerShapingParameters,
allowlistedRewardDenoms *AllowlistedRewardDenoms,
allowlistedRewardDenoms *AllowlistedRewardDenoms, newChainId string,
) (*MsgUpdateConsumer, error) {
return &MsgUpdateConsumer{
Owner: owner,
Expand All @@ -353,6 +353,7 @@ func NewMsgUpdateConsumer(owner, consumerId, ownerAddress string, metadata *Cons
InitializationParameters: initializationParameters,
PowerShapingParameters: powerShapingParameters,
AllowlistedRewardDenoms: allowlistedRewardDenoms,
NewChainId: newChainId,
}, nil
}

Expand Down Expand Up @@ -388,6 +389,11 @@ func (msg MsgUpdateConsumer) ValidateBasic() error {
}
}

if strings.TrimSpace(msg.NewChainId) != "" && len(msg.NewChainId) > cmttypes.MaxChainIDLen {
return errorsmod.Wrapf(ErrInvalidMsgUpdateConsumer, "NewChainId (%s) is too long; got: %d, max: %d",
msg.NewChainId, len(msg.NewChainId), cmttypes.MaxChainIDLen)
}

return nil
}

Expand Down
13 changes: 12 additions & 1 deletion x/ccv/provider/types/msg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ func TestMsgUpdateConsumerValidateBasic(t *testing.T) {
testCases := []struct {
name string
powerShapingParameters types.PowerShapingParameters
newChainId string
expPass bool
}{
{
Expand All @@ -504,6 +505,7 @@ func TestMsgUpdateConsumerValidateBasic(t *testing.T) {
AllowInactiveVals: false,
Prioritylist: []string{consAddr1},
},
"validchainid-0",
true,
},
{
Expand All @@ -516,6 +518,7 @@ func TestMsgUpdateConsumerValidateBasic(t *testing.T) {
Denylist: nil,
Prioritylist: nil,
},
"validchainid-0",
false,
},
{
Expand All @@ -530,6 +533,7 @@ func TestMsgUpdateConsumerValidateBasic(t *testing.T) {
AllowInactiveVals: false,
Prioritylist: nil,
},
"validchainid-0",
false,
},
{
Expand All @@ -544,13 +548,20 @@ func TestMsgUpdateConsumerValidateBasic(t *testing.T) {
AllowInactiveVals: false,
Prioritylist: []string{consAddr1},
},
"validchainid-0",
true,
},
{
"too long new chain id",
types.PowerShapingParameters{},
"this is an extremely long chain id that is so long that the validation would fail",
false,
},
}

for _, tc := range testCases {
// TODO (PERMISSIONLESS) add more tests
msg, _ := types.NewMsgUpdateConsumer("", "0", "cosmos1p3ucd3ptpw902fluyjzhq3ffgq4ntddac9sa3s", nil, nil, &tc.powerShapingParameters, nil)
msg, _ := types.NewMsgUpdateConsumer("", "0", "cosmos1p3ucd3ptpw902fluyjzhq3ffgq4ntddac9sa3s", nil, nil, &tc.powerShapingParameters, nil, tc.newChainId)
err := msg.ValidateBasic()
if tc.expPass {
require.NoError(t, err, "valid case: %s should not return error. got %w", tc.name, err)
Expand Down
Loading

0 comments on commit 81907cb

Please sign in to comment.