Skip to content

Commit 0600f7f

Browse files
authored
fix: do not allow the update of initialization parameters of launched chains and stop a chain from launching if (#2245)
* init commit * took into account comments
1 parent 97daa92 commit 0600f7f

File tree

3 files changed

+107
-6
lines changed

3 files changed

+107
-6
lines changed

x/ccv/provider/keeper/consumer_lifecycle.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525
// PrepareConsumerForLaunch prepares to move the launch of a consumer chain from the previous spawn time to spawn time.
2626
// Previous spawn time can correspond to its zero value if the validator was not previously set for launch.
2727
func (k Keeper) PrepareConsumerForLaunch(ctx sdk.Context, consumerId string, previousSpawnTime, spawnTime time.Time) error {
28-
if !previousSpawnTime.Equal(time.Time{}) {
28+
if !previousSpawnTime.IsZero() {
2929
// if this is not the first initialization and hence `previousSpawnTime` does not contain the zero value of `Time`
3030
// remove the consumer id from the previous spawn time
3131
err := k.RemoveConsumerToBeLaunched(ctx, consumerId, previousSpawnTime)

x/ccv/provider/keeper/msg_server.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ func (k msgServer) UpdateConsumer(goCtx context.Context, msg *types.MsgUpdateCon
494494
eventAttributes = append(eventAttributes, sdk.NewAttribute(types.AttributeConsumerName, msg.Metadata.Name))
495495
}
496496

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

505505
if msg.InitializationParameters != nil {
506+
phase := k.GetConsumerPhase(ctx, consumerId)
507+
508+
if phase == types.CONSUMER_PHASE_LAUNCHED {
509+
return &resp, errorsmod.Wrap(types.ErrInvalidMsgUpdateConsumer,
510+
"cannot update the initialization parameters of an an already launched chain; "+
511+
"do not provide any initialization parameters when updating a launched chain")
512+
}
513+
514+
if msg.InitializationParameters.SpawnTime.IsZero() {
515+
if phase == types.CONSUMER_PHASE_INITIALIZED {
516+
// chain was previously ready to launch at `previousSpawnTime` so we remove the
517+
// consumer from getting launched and move it back to the Registered phase
518+
err = k.RemoveConsumerToBeLaunched(ctx, consumerId, previousSpawnTime)
519+
if err != nil {
520+
return &resp, errorsmod.Wrapf(types.ErrInvalidMsgUpdateConsumer,
521+
"cannot remove the consumer from being launched: %s", err.Error())
522+
}
523+
k.SetConsumerPhase(ctx, consumerId, types.CONSUMER_PHASE_REGISTERED)
524+
}
525+
}
526+
// add SpawnTime event attribute
527+
eventAttributes = append(eventAttributes,
528+
sdk.NewAttribute(types.AttributeConsumerSpawnTime, msg.InitializationParameters.SpawnTime.String()))
529+
506530
if err = k.Keeper.SetConsumerInitializationParameters(ctx, msg.ConsumerId, *msg.InitializationParameters); err != nil {
507531
return &resp, errorsmod.Wrapf(types.ErrInvalidConsumerInitializationParameters,
508532
"cannot set consumer initialization parameters: %s", err.Error())
@@ -562,10 +586,6 @@ func (k msgServer) UpdateConsumer(goCtx context.Context, msg *types.MsgUpdateCon
562586
return &resp, errorsmod.Wrapf(ccvtypes.ErrInvalidConsumerState,
563587
"cannot prepare chain with consumer id (%s) for launch", consumerId)
564588
}
565-
566-
// add SpawnTime event attribute
567-
eventAttributes = append(eventAttributes,
568-
sdk.NewAttribute(types.AttributeConsumerSpawnTime, msg.InitializationParameters.SpawnTime.String()))
569589
}
570590

571591
// add Owner event attribute

x/ccv/provider/keeper/msg_server_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package keeper_test
22

33
import (
4+
"github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
45
"testing"
56
"time"
67

@@ -176,4 +177,84 @@ func TestUpdateConsumer(t *testing.T) {
176177
require.Equal(t, providertypes.ConsumerIds{
177178
Ids: []string{consumerId},
178179
}, consumerIds)
180+
181+
// assert that we CANNOT update the initialization parameters of a launched chain
182+
providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_LAUNCHED)
183+
_, err = msgServer.UpdateConsumer(ctx,
184+
&providertypes.MsgUpdateConsumer{
185+
Owner: expectedOwnerAddress, ConsumerId: consumerId,
186+
Metadata: nil,
187+
InitializationParameters: &expectedInitializationParameters,
188+
PowerShapingParameters: nil,
189+
})
190+
require.ErrorContains(t, err, "cannot update the initialization parameters of an an already launched chain")
191+
192+
// assert that we can update the consumer metadata of a launched chain
193+
providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_LAUNCHED)
194+
expectedConsumerMetadata.Name = "name of a launched chain"
195+
_, err = msgServer.UpdateConsumer(ctx,
196+
&providertypes.MsgUpdateConsumer{
197+
Owner: expectedOwnerAddress, ConsumerId: consumerId,
198+
Metadata: &expectedConsumerMetadata,
199+
InitializationParameters: nil,
200+
PowerShapingParameters: nil,
201+
})
202+
require.NoError(t, err)
203+
actualConsumerMetadata, err = providerKeeper.GetConsumerMetadata(ctx, consumerId)
204+
require.NoError(t, err)
205+
require.Equal(t, expectedConsumerMetadata, actualConsumerMetadata)
206+
207+
// assert that we can update the power-shaping parameters of a launched chain
208+
providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_LAUNCHED)
209+
expectedPowerShapingParameters.ValidatorSetCap = 123
210+
_, err = msgServer.UpdateConsumer(ctx,
211+
&providertypes.MsgUpdateConsumer{
212+
Owner: expectedOwnerAddress, ConsumerId: consumerId,
213+
Metadata: nil,
214+
InitializationParameters: nil,
215+
PowerShapingParameters: &expectedPowerShapingParameters,
216+
})
217+
require.NoError(t, err)
218+
actualPowerShapingParameters, err = providerKeeper.GetConsumerPowerShapingParameters(ctx, consumerId)
219+
require.NoError(t, err)
220+
require.Equal(t, expectedPowerShapingParameters, actualPowerShapingParameters)
221+
222+
// assert that if we call `MsgUpdateConsumer` with a spawn time of zero on an initialized chain, the chain
223+
// will not be scheduled to launch and will move back to its Registered phase
224+
providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.CONSUMER_PHASE_INITIALIZED)
225+
// first assert that the chain is scheduled to launch
226+
previousSpawnTime = expectedInitializationParameters.SpawnTime
227+
consumerIds, err = providerKeeper.GetConsumersToBeLaunched(ctx, previousSpawnTime)
228+
require.NoError(t, err)
229+
require.Equal(t, providertypes.ConsumerIds{
230+
Ids: []string{consumerId},
231+
}, consumerIds)
232+
233+
// then, update with a spawn time of zero to prevent the chain from launching
234+
expectedInitializationParameters.SpawnTime = time.Time{}
235+
// also update an arbitrary field of the initialization parameters
236+
// to verify that the parameters of the chain get updated
237+
expectedInitializationParameters.InitialHeight = types.NewHeight(1, 123456)
238+
_, err = msgServer.UpdateConsumer(ctx,
239+
&providertypes.MsgUpdateConsumer{
240+
Owner: expectedOwnerAddress, ConsumerId: consumerId,
241+
Metadata: nil,
242+
InitializationParameters: &expectedInitializationParameters,
243+
PowerShapingParameters: nil,
244+
})
245+
// assert the chain is not scheduled to launch
246+
consumerIds, err = providerKeeper.GetConsumersToBeLaunched(ctx, previousSpawnTime)
247+
require.NoError(t, err)
248+
require.Empty(t, consumerIds)
249+
// also assert that no chain is scheduled to launch at zero time
250+
consumerIds, err = providerKeeper.GetConsumersToBeLaunched(ctx, time.Time{})
251+
require.NoError(t, err)
252+
require.Empty(t, consumerIds)
253+
// assert that the chain has moved to the registered phase because it is not ready to launch
254+
phase = providerKeeper.GetConsumerPhase(ctx, consumerId)
255+
require.Equal(t, providertypes.CONSUMER_PHASE_REGISTERED, phase)
256+
// assert that the initialization parameters of the chain were nevertheless updated
257+
actualInitializationParameters, err = providerKeeper.GetConsumerInitializationParameters(ctx, consumerId)
258+
require.NoError(t, err)
259+
require.Equal(t, expectedInitializationParameters, actualInitializationParameters)
179260
}

0 commit comments

Comments
 (0)