Skip to content

Commit

Permalink
remove LockUnbonding flag and references from repo (PR #551)
Browse files Browse the repository at this point in the history
  • Loading branch information
MSalopek committed Dec 7, 2022
1 parent 49798dd commit 41e219e
Show file tree
Hide file tree
Showing 15 changed files with 217 additions and 370 deletions.
11 changes: 4 additions & 7 deletions proto/interchain_security/ccv/provider/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,15 @@ message ConsumerState {
string client_id = 3;
// InitalHeight defines the initial block height for the consumer chain
uint64 initial_height = 4;
// LockUnbondingOnTimeout defines whether the unbonding funds should be released for this
// chain in case of a IBC channel timeout
bool lock_unbonding_on_timeout = 5;
// ConsumerGenesis defines the initial consumer chain genesis states
interchain_security.ccv.consumer.v1.GenesisState consumer_genesis = 6
interchain_security.ccv.consumer.v1.GenesisState consumer_genesis = 5
[ (gogoproto.nullable) = false ];
// PendingValsetChanges defines the pending validator set changes for the consumer chain
repeated interchain_security.ccv.v1.ValidatorSetChangePacketData pending_valset_changes = 7
repeated interchain_security.ccv.v1.ValidatorSetChangePacketData pending_valset_changes = 6
[ (gogoproto.nullable) = false ];
repeated string slash_downtime_ack = 8;
repeated string slash_downtime_ack = 7;
// UnbondingOpsIndex defines the unbonding operations on the consumer chain
repeated UnbondingOpIndex unbonding_ops_index = 9
repeated UnbondingOpIndex unbonding_ops_index = 8
[ (gogoproto.nullable) = false ];
}

Expand Down
18 changes: 7 additions & 11 deletions proto/interchain_security/ccv/provider/v1/provider.proto
Original file line number Diff line number Diff line change
Expand Up @@ -37,42 +37,38 @@ message ConsumerAdditionProposal {
// will be responsible for starting their consumer chain validator node.
google.protobuf.Timestamp spawn_time = 7
[(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
// Indicates whether the outstanding unbonding operations should be released
// in case of a channel time-outs. When set to true, a governance proposal
// on the provider chain would be necessary to release the locked funds.
bool lock_unbonding_on_timeout = 8;

// BlocksPerDistributionTransmission is the number of blocks between ibc-token-transfers from the consumer chain to the provider chain.
// Note that at this transmission event a fraction of the accumulated tokens are divided and sent consumer redistribution address.
int64 blocks_per_distribution_transmission = 9;
int64 blocks_per_distribution_transmission = 8;

// Sent CCV related IBC packets will timeout after this duration
google.protobuf.Duration ccv_timeout_period = 10
google.protobuf.Duration ccv_timeout_period = 9
[(gogoproto.nullable) = false, (gogoproto.stdduration) = true];

// Sent transfer related IBC packets will timeout after this duration
google.protobuf.Duration transfer_timeout_period = 11
google.protobuf.Duration transfer_timeout_period = 10
[(gogoproto.nullable) = false, (gogoproto.stdduration) = true];

// The fraction of tokens allocated to the consumer redistribution address
// during distribution events. The fraction is a string representing a
// decimal number. For example "0.75" would represent 75%.
string consumer_redistribution_fraction = 12;
string consumer_redistribution_fraction = 11;

// The number of historical info entries to persist in store.
// This param is a part of the cosmos sdk staking module. In the case of
// a ccv enabled consumer chain, the ccv module acts as the staking module.
int64 historical_entries = 13;
int64 historical_entries = 12;

// Unbonding period for the consumer,
// which should be smaller than that of the provider in general.
google.protobuf.Duration unbonding_period = 14
google.protobuf.Duration unbonding_period = 13
[(gogoproto.nullable) = false, (gogoproto.stdduration) = true];
}

// ConsumerRemovalProposal is a governance proposal on the provider chain to remove (and stop) a consumer chain.
// If it passes, all the consumer chain's state is removed from the provider chain. The outstanding unbonding
// operation funds are released if the LockUnbondingOnTimeout parameter is set to false for the consumer chain ID.
// operation funds are released.
message ConsumerRemovalProposal {
// the title of the proposal
string title = 1;
Expand Down
8 changes: 3 additions & 5 deletions tests/e2e/stop_consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() {
// - setup CCV channel; establish CCV channel and set channelToChain, chainToChannel and initHeight mapping for the consumer chain ID
// - delegate the total bond amount to the chosed validator
// - undelegate the shares in four consecutive blocks evenly; create UnbondigOp and UnbondingOpIndex entries for the consumer chain ID
// - set SlashAck and LockUnbondingOnTimeout states for the consumer chain ID
// - set SlashAck state for the consumer chain ID
setupOperations := []struct {
fn func(suite *CCVTestSuite) error
}{
Expand Down Expand Up @@ -76,7 +76,6 @@ func (s *CCVTestSuite) TestStopConsumerChain() {
{
func(suite *CCVTestSuite) error {
providerKeeper.SetSlashAcks(s.providerCtx(), consumerChainID, []string{"validator-1", "validator-2", "validator-3"})
providerKeeper.SetLockUnbondingOnTimeout(s.providerCtx(), consumerChainID)
providerKeeper.AppendPendingPackets(s.providerCtx(), consumerChainID, ccv.ValidatorSetChangePacketData{ValsetUpdateId: 1})
return nil
},
Expand All @@ -89,7 +88,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() {
}

// stop the consumer chain
err = providerKeeper.StopConsumerChain(s.providerCtx(), consumerChainID, false, true)
err = providerKeeper.StopConsumerChain(s.providerCtx(), consumerChainID, true)
s.Require().NoError(err)

// check all states are removed and the unbonding operation released
Expand All @@ -106,7 +105,7 @@ func (s *CCVTestSuite) TestStopConsumerOnChannelClosed() {
providerKeeper := s.providerApp.GetProviderKeeper()

// stop the consumer chain
err := providerKeeper.StopConsumerChain(s.providerCtx(), s.consumerChain.ChainID, true, true)
err := providerKeeper.StopConsumerChain(s.providerCtx(), s.consumerChain.ChainID, true)
s.Require().NoError(err)

err = s.path.EndpointA.UpdateClient()
Expand Down Expand Up @@ -160,7 +159,6 @@ func (s *CCVTestSuite) checkConsumerChainIsRemoved(chainID string, lockUbd bool,
// verify consumer chain's states are removed
_, found := providerKeeper.GetConsumerGenesis(s.providerCtx(), chainID)
s.Require().False(found)
s.Require().False(providerKeeper.GetLockUnbondingOnTimeout(s.providerCtx(), chainID))
_, found = providerKeeper.GetConsumerClientId(s.providerCtx(), chainID)
s.Require().False(found)

Expand Down
10 changes: 3 additions & 7 deletions x/ccv/provider/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) {
if err := k.SetConsumerGenesis(ctx, chainID, cs.ConsumerGenesis); err != nil {
panic(fmt.Errorf("consumer chain genesis could not be persisted: %w", err))
}
if cs.LockUnbondingOnTimeout {
k.SetLockUnbondingOnTimeout(ctx, chainID)
}
// check if the CCV channel was established
if cs.ChannelId != "" {
k.SetChannelToChain(ctx, cs.ChannelId, chainID)
Expand Down Expand Up @@ -105,10 +102,9 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {

// initial consumer chain states
cs := types.ConsumerState{
ChainId: chainID,
ClientId: clientID,
ConsumerGenesis: gen,
LockUnbondingOnTimeout: k.GetLockUnbondingOnTimeout(ctx, chainID),
ChainId: chainID,
ClientId: clientID,
ConsumerGenesis: gen,
}

// try to find channel id for the current consumer chain
Expand Down
2 changes: 0 additions & 2 deletions x/ccv/provider/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,6 @@ func assertConsumerChainStates(ctx sdk.Context, t *testing.T, pk keeper.Keeper,
require.True(t, found)
}

require.Equal(t, cs.LockUnbondingOnTimeout, pk.GetLockUnbondingOnTimeout(ctx, chainID))

if expVSC := cs.GetPendingValsetChanges(); expVSC != nil {
gotVSC := pk.GetPendingPackets(ctx, chainID)
require.Equal(t, expVSC, gotVSC)
Expand Down
20 changes: 0 additions & 20 deletions x/ccv/provider/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -715,26 +715,6 @@ func (k Keeper) DeletePendingPackets(ctx sdk.Context, chainID string) {
store.Delete(types.PendingVSCsKey(chainID))
}

// GetLockUnbondingOnTimeout returns the mapping from the given consumer chain ID to a boolean value indicating whether
// the unbonding operation funds should be locked on CCV channel timeout
func (k Keeper) GetLockUnbondingOnTimeout(ctx sdk.Context, chainID string) bool {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.LockUnbondingOnTimeoutKey(chainID))
return bz != nil
}

// SetLockUnbondingOnTimeout locks the unbonding operation funds in case of a CCV channel timeouts for the given consumer chain ID
func (k Keeper) SetLockUnbondingOnTimeout(ctx sdk.Context, chainID string) {
store := ctx.KVStore(k.storeKey)
store.Set(types.LockUnbondingOnTimeoutKey(chainID), []byte{})
}

// DeleteLockUnbondingOnTimeout deletes the unbonding operation lock in case of a CCV channel timeouts for the given consumer chain ID
func (k Keeper) DeleteLockUnbondingOnTimeout(ctx sdk.Context, chainID string) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.LockUnbondingOnTimeoutKey(chainID))
}

// SetConsumerClientId sets the client ID for the given chain ID
func (k Keeper) SetConsumerClientId(ctx sdk.Context, chainID, clientID string) {
store := ctx.KVStore(k.storeKey)
Expand Down
63 changes: 30 additions & 33 deletions x/ccv/provider/keeper/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func (k Keeper) CreateConsumerClient(ctx sdk.Context, prop *types.ConsumerAdditi
func (k Keeper) HandleConsumerRemovalProposal(ctx sdk.Context, p *types.ConsumerRemovalProposal) error {

if !ctx.BlockTime().Before(p.StopTime) {
return k.StopConsumerChain(ctx, p.ChainId, false, true)
return k.StopConsumerChain(ctx, p.ChainId, true)
}

k.SetPendingConsumerRemovalProp(ctx, p.ChainId, p.StopTime)
Expand All @@ -129,7 +129,7 @@ func (k Keeper) HandleConsumerRemovalProposal(ctx sdk.Context, p *types.Consumer
// This method implements StopConsumerChain from spec.
// See: https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/methods.md#ccv-pcf-stcc1
// Spec tag: [CCV-PCF-STCC.1]
func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, lockUbd, closeChan bool) (err error) {
func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, closeChan bool) (err error) {
// check that a client for chainID exists
if _, found := k.GetConsumerClientId(ctx, chainID); !found {
// drop the proposal
Expand All @@ -139,7 +139,6 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, lockUbd, clos
// clean up states
k.DeleteConsumerClientId(ctx, chainID)
k.DeleteConsumerGenesis(ctx, chainID)
k.DeleteLockUnbondingOnTimeout(ctx, chainID)
k.DeleteInitTimeoutTimestamp(ctx, chainID)
k.DeleteKeyAssignments(ctx, chainID)

Expand All @@ -166,38 +165,36 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, lockUbd, clos
k.ConsumeSlashAcks(ctx, chainID)
k.DeletePendingPackets(ctx, chainID)

// release unbonding operations if they aren't locked
// release unbonding operations
var vscIDs []uint64
if !lockUbd {
// iterate over the consumer chain's unbonding operation VSC ids
k.IterateOverUnbondingOpIndex(ctx, chainID, func(vscID uint64, ids []uint64) (stop bool) {
// iterate over the unbonding operations for the current VSC ID
var maturedIds []uint64
for _, id := range ids {
unbondingOp, found := k.GetUnbondingOp(ctx, id)
if !found {
err = fmt.Errorf("could not find UnbondingOp according to index - id: %d", id)
return true // stop the iteration
}
// remove consumer chain ID from unbonding op record
unbondingOp.UnbondingConsumerChains, _ = removeStringFromSlice(unbondingOp.UnbondingConsumerChains, chainID)

// If unbonding op is completely unbonded from all relevant consumer chains
if len(unbondingOp.UnbondingConsumerChains) == 0 {
// Store id of matured unbonding op for later completion of unbonding in staking module
maturedIds = append(maturedIds, unbondingOp.Id)
// Delete unbonding op
k.DeleteUnbondingOp(ctx, unbondingOp.Id)
} else {
k.SetUnbondingOp(ctx, unbondingOp)
}
// iterate over the consumer chain's unbonding operation VSC ids
k.IterateOverUnbondingOpIndex(ctx, chainID, func(vscID uint64, ids []uint64) (stop bool) {
// iterate over the unbonding operations for the current VSC ID
var maturedIds []uint64
for _, id := range ids {
unbondingOp, found := k.GetUnbondingOp(ctx, id)
if !found {
err = fmt.Errorf("could not find UnbondingOp according to index - id: %d", id)
return true // stop the iteration
}
k.AppendMaturedUnbondingOps(ctx, maturedIds)
// remove consumer chain ID from unbonding op record
unbondingOp.UnbondingConsumerChains, _ = removeStringFromSlice(unbondingOp.UnbondingConsumerChains, chainID)

// If unbonding op is completely unbonded from all relevant consumer chains
if len(unbondingOp.UnbondingConsumerChains) == 0 {
// Store id of matured unbonding op for later completion of unbonding in staking module
maturedIds = append(maturedIds, unbondingOp.Id)
// Delete unbonding op
k.DeleteUnbondingOp(ctx, unbondingOp.Id)
} else {
k.SetUnbondingOp(ctx, unbondingOp)
}
}
k.AppendMaturedUnbondingOps(ctx, maturedIds)

vscIDs = append(vscIDs, vscID)
return false // do not stop the iteration
})
}
vscIDs = append(vscIDs, vscID)
return false // do not stop the iteration
})

if err != nil {
return err
Expand Down Expand Up @@ -463,7 +460,7 @@ func (k Keeper) BeginBlockCCR(ctx sdk.Context) {
propsToExecute := k.ConsumerRemovalPropsToExecute(ctx)

for _, prop := range propsToExecute {
err := k.StopConsumerChain(ctx, prop.ChainId, false, true)
err := k.StopConsumerChain(ctx, prop.ChainId, true)
if err != nil {
panic(fmt.Errorf("consumer chain failed to stop: %w", err))
}
Expand Down
11 changes: 1 addition & 10 deletions x/ccv/provider/keeper/proposal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,6 @@ func TestHandleConsumerAdditionProposal(t *testing.T) {
)
}

tc.prop.LockUnbondingOnTimeout = false // Full functionality not implemented yet.

err := providerKeeper.HandleConsumerAdditionProposal(ctx, tc.prop)
require.NoError(t, err)

Expand Down Expand Up @@ -200,10 +198,6 @@ func testCreatedConsumerClient(t *testing.T,
require.True(t, found, "consumer client not found")
require.Equal(t, expectedClientID, clientId)

// Lock unbonding on timeout flag always false for now.
lockUbdOnTimeout := providerKeeper.GetLockUnbondingOnTimeout(ctx, expectedChainID)
require.False(t, lockUbdOnTimeout)

// Only assert that consumer genesis was set,
// more granular tests on consumer genesis should be defined in TestMakeConsumerGenesis
_, ok := providerKeeper.GetConsumerGenesis(ctx, expectedChainID)
Expand Down Expand Up @@ -451,7 +445,7 @@ func TestStopConsumerChain(t *testing.T) {
// Setup specific to test case
tc.setup(ctx, &providerKeeper, mocks)

err := providerKeeper.StopConsumerChain(ctx, "chainID", false, true)
err := providerKeeper.StopConsumerChain(ctx, "chainID", true)

if tc.expErr {
require.Error(t, err)
Expand All @@ -471,8 +465,6 @@ func testProviderStateIsCleaned(t *testing.T, ctx sdk.Context, providerKeeper pr

_, found := providerKeeper.GetConsumerClientId(ctx, expectedChainID)
require.False(t, found)
found = providerKeeper.GetLockUnbondingOnTimeout(ctx, expectedChainID)
require.False(t, found)
_, found = providerKeeper.GetChainToChannel(ctx, expectedChainID)
require.False(t, found)
_, found = providerKeeper.GetChannelToChain(ctx, expectedChannelID)
Expand Down Expand Up @@ -695,7 +687,6 @@ func TestMakeConsumerGenesis(t *testing.T) {
Title: "title",
Description: "desc",
ChainId: "testchain1",
LockUnbondingOnTimeout: false,
BlocksPerDistributionTransmission: 1000,
CcvTimeoutPeriod: 2419200000000000,
TransferTimeoutPeriod: 3600000000000,
Expand Down
22 changes: 7 additions & 15 deletions x/ccv/provider/keeper/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,8 @@ func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Pac
// The VSC packet data could not be successfully decoded.
// This should never happen.
if chainID, ok := k.GetChannelToChain(ctx, packet.SourceChannel); ok {
// stop consumer chain and uses the LockUnbondingOnTimeout flag
// to decide whether the unbonding operations should be released
return k.StopConsumerChain(ctx, chainID, k.GetLockUnbondingOnTimeout(ctx, chainID), false)
// stop consumer chain and release unbonding
return k.StopConsumerChain(ctx, chainID, false)
}
return sdkerrors.Wrapf(types.ErrUnknownConsumerChannelId, "recv ErrorAcknowledgement on unknown channel %s", packet.SourceChannel)
}
Expand All @@ -127,9 +126,8 @@ func (k Keeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet) err
packet.SourceChannel,
)
}
// stop consumer chain and uses the LockUnbondingOnTimeout flag
// to decide whether the unbonding operations should be released
return k.StopConsumerChain(ctx, chainID, k.GetLockUnbondingOnTimeout(ctx, chainID), false)
// stop consumer chain and release unbondings
return k.StopConsumerChain(ctx, chainID, false)
}

// EndBlockVSU contains the EndBlock logic needed for
Expand Down Expand Up @@ -381,7 +379,7 @@ func (k Keeper) EndBlockCCR(ctx sdk.Context) {
// stop the consumer chain and unlock the unbonding.
// Note that the CCV channel was not established,
// thus closeChan is irrelevant
err := k.StopConsumerChain(ctx, chainID, false, false)
err := k.StopConsumerChain(ctx, chainID, false)
if err != nil {
panic(fmt.Errorf("consumer chain failed to stop: %w", err))
}
Expand Down Expand Up @@ -410,14 +408,8 @@ func (k Keeper) EndBlockCCR(ctx sdk.Context) {
})
// remove consumers that timed out
for _, chainID := range chainIdsToRemove {
// stop the consumer chain and use lockUnbondingOnTimeout
// to decide whether to lock the unbonding
err := k.StopConsumerChain(
ctx,
chainID,
k.GetLockUnbondingOnTimeout(ctx, chainID),
true,
)
// stop the consumer chain and release unbondings
err := k.StopConsumerChain(ctx, chainID, true)
if err != nil {
panic(fmt.Errorf("consumer chain failed to stop: %w", err))
}
Expand Down
17 changes: 8 additions & 9 deletions x/ccv/provider/types/consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@ func NewConsumerStates(
slashDowntimeAck []string,
) ConsumerState {
return ConsumerState{
ChainId: chainID,
ClientId: clientID,
ChannelId: channelID,
InitialHeight: initialHeight,
LockUnbondingOnTimeout: true,
UnbondingOpsIndex: unbondingOpsIndexes,
PendingValsetChanges: pendingValsetChanges,
ConsumerGenesis: genesis,
SlashDowntimeAck: slashDowntimeAck,
ChainId: chainID,
ClientId: clientID,
ChannelId: channelID,
InitialHeight: initialHeight,
UnbondingOpsIndex: unbondingOpsIndexes,
PendingValsetChanges: pendingValsetChanges,
ConsumerGenesis: genesis,
SlashDowntimeAck: slashDowntimeAck,
}
}
Loading

0 comments on commit 41e219e

Please sign in to comment.