Skip to content

Commit

Permalink
fix: do not allow the update of initialization parameters of launched…
Browse files Browse the repository at this point in the history
… chains and stop a chain from launching if (#2245)

* init commit

* took into account comments
  • Loading branch information
insumity committed Sep 10, 2024
1 parent 97daa92 commit 0600f7f
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 6 deletions.
2 changes: 1 addition & 1 deletion x/ccv/provider/keeper/consumer_lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
// PrepareConsumerForLaunch prepares to move the launch of a consumer chain from the previous spawn time to spawn time.
// Previous spawn time can correspond to its zero value if the validator was not previously set for launch.
func (k Keeper) PrepareConsumerForLaunch(ctx sdk.Context, consumerId string, previousSpawnTime, spawnTime time.Time) error {
if !previousSpawnTime.Equal(time.Time{}) {
if !previousSpawnTime.IsZero() {
// if this is not the first initialization and hence `previousSpawnTime` does not contain the zero value of `Time`
// remove the consumer id from the previous spawn time
err := k.RemoveConsumerToBeLaunched(ctx, consumerId, previousSpawnTime)
Expand Down
30 changes: 25 additions & 5 deletions x/ccv/provider/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ func (k msgServer) UpdateConsumer(goCtx context.Context, msg *types.MsgUpdateCon
eventAttributes = append(eventAttributes, sdk.NewAttribute(types.AttributeConsumerName, msg.Metadata.Name))
}

// get the previous spawn time so that we can use it in `PrepareConsumerForLaunch`
// get the previous spawn time so that we can remove its previously planned spawn time if a new spawn time is provided
previousInitializationParameters, err := k.Keeper.GetConsumerInitializationParameters(ctx, consumerId)
if err != nil {
return &resp, errorsmod.Wrapf(ccvtypes.ErrInvalidConsumerState,
Expand All @@ -503,6 +503,30 @@ func (k msgServer) UpdateConsumer(goCtx context.Context, msg *types.MsgUpdateCon
previousSpawnTime := previousInitializationParameters.SpawnTime

if msg.InitializationParameters != nil {
phase := k.GetConsumerPhase(ctx, consumerId)

if phase == types.CONSUMER_PHASE_LAUNCHED {
return &resp, errorsmod.Wrap(types.ErrInvalidMsgUpdateConsumer,
"cannot update the initialization parameters of an an already launched chain; "+
"do not provide any initialization parameters when updating a launched chain")
}

if msg.InitializationParameters.SpawnTime.IsZero() {
if phase == types.CONSUMER_PHASE_INITIALIZED {
// chain was previously ready to launch at `previousSpawnTime` so we remove the
// consumer from getting launched and move it back to the Registered phase
err = k.RemoveConsumerToBeLaunched(ctx, consumerId, previousSpawnTime)
if err != nil {
return &resp, errorsmod.Wrapf(types.ErrInvalidMsgUpdateConsumer,
"cannot remove the consumer from being launched: %s", err.Error())
}
k.SetConsumerPhase(ctx, consumerId, types.CONSUMER_PHASE_REGISTERED)
}
}
// add SpawnTime event attribute
eventAttributes = append(eventAttributes,
sdk.NewAttribute(types.AttributeConsumerSpawnTime, msg.InitializationParameters.SpawnTime.String()))

if err = k.Keeper.SetConsumerInitializationParameters(ctx, msg.ConsumerId, *msg.InitializationParameters); err != nil {
return &resp, errorsmod.Wrapf(types.ErrInvalidConsumerInitializationParameters,
"cannot set consumer initialization parameters: %s", err.Error())
Expand Down Expand Up @@ -562,10 +586,6 @@ func (k msgServer) UpdateConsumer(goCtx context.Context, msg *types.MsgUpdateCon
return &resp, errorsmod.Wrapf(ccvtypes.ErrInvalidConsumerState,
"cannot prepare chain with consumer id (%s) for launch", consumerId)
}

// add SpawnTime event attribute
eventAttributes = append(eventAttributes,
sdk.NewAttribute(types.AttributeConsumerSpawnTime, msg.InitializationParameters.SpawnTime.String()))
}

// add Owner event attribute
Expand Down
81 changes: 81 additions & 0 deletions x/ccv/provider/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper_test

import (
"github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
"testing"
"time"

Expand Down Expand Up @@ -176,4 +177,84 @@ func TestUpdateConsumer(t *testing.T) {
require.Equal(t, providertypes.ConsumerIds{
Ids: []string{consumerId},
}, consumerIds)

// assert that we CANNOT update the initialization parameters 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: &expectedInitializationParameters,
PowerShapingParameters: nil,
})
require.ErrorContains(t, err, "cannot update the initialization parameters of an an already launched chain")

// 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"
_, err = msgServer.UpdateConsumer(ctx,
&providertypes.MsgUpdateConsumer{
Owner: expectedOwnerAddress, ConsumerId: consumerId,
Metadata: &expectedConsumerMetadata,
InitializationParameters: nil,
PowerShapingParameters: nil,
})
require.NoError(t, err)
actualConsumerMetadata, err = providerKeeper.GetConsumerMetadata(ctx, consumerId)
require.NoError(t, err)
require.Equal(t, expectedConsumerMetadata, actualConsumerMetadata)

// assert that we can update the power-shaping parameters of a launched chain
providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_LAUNCHED)
expectedPowerShapingParameters.ValidatorSetCap = 123
_, err = msgServer.UpdateConsumer(ctx,
&providertypes.MsgUpdateConsumer{
Owner: expectedOwnerAddress, ConsumerId: consumerId,
Metadata: nil,
InitializationParameters: nil,
PowerShapingParameters: &expectedPowerShapingParameters,
})
require.NoError(t, err)
actualPowerShapingParameters, err = providerKeeper.GetConsumerPowerShapingParameters(ctx, consumerId)
require.NoError(t, err)
require.Equal(t, expectedPowerShapingParameters, actualPowerShapingParameters)

// assert that if we call `MsgUpdateConsumer` with a spawn time of zero on an initialized chain, the chain
// will not be scheduled to launch and will move back to its Registered phase
providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_INITIALIZED)
// first assert that the chain is scheduled to launch
previousSpawnTime = expectedInitializationParameters.SpawnTime
consumerIds, err = providerKeeper.GetConsumersToBeLaunched(ctx, previousSpawnTime)
require.NoError(t, err)
require.Equal(t, providertypes.ConsumerIds{
Ids: []string{consumerId},
}, consumerIds)

// then, update with a spawn time of zero to prevent the chain from launching
expectedInitializationParameters.SpawnTime = time.Time{}
// also update an arbitrary field of the initialization parameters
// to verify that the parameters of the chain get updated
expectedInitializationParameters.InitialHeight = types.NewHeight(1, 123456)
_, err = msgServer.UpdateConsumer(ctx,
&providertypes.MsgUpdateConsumer{
Owner: expectedOwnerAddress, ConsumerId: consumerId,
Metadata: nil,
InitializationParameters: &expectedInitializationParameters,
PowerShapingParameters: nil,
})
// assert the chain is not scheduled to launch
consumerIds, err = providerKeeper.GetConsumersToBeLaunched(ctx, previousSpawnTime)
require.NoError(t, err)
require.Empty(t, consumerIds)
// also assert that no chain is scheduled to launch at zero time
consumerIds, err = providerKeeper.GetConsumersToBeLaunched(ctx, time.Time{})
require.NoError(t, err)
require.Empty(t, consumerIds)
// assert that the chain has moved to the registered phase because it is not ready to launch
phase = providerKeeper.GetConsumerPhase(ctx, consumerId)
require.Equal(t, providertypes.CONSUMER_PHASE_REGISTERED, phase)
// assert that the initialization parameters of the chain were nevertheless updated
actualInitializationParameters, err = providerKeeper.GetConsumerInitializationParameters(ctx, consumerId)
require.NoError(t, err)
require.Equal(t, expectedInitializationParameters, actualInitializationParameters)
}

0 comments on commit 0600f7f

Please sign in to comment.