-
Notifications
You must be signed in to change notification settings - Fork 138
/
genesis.go
169 lines (144 loc) · 5.88 KB
/
genesis.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/interchain-security/v6/x/ccv/consumer/types"
ccv "github.com/cosmos/interchain-security/v6/x/ccv/types"
)
// InitGenesis initializes the CCV consumer state and binds to PortID.
// The three states in which a consumer chain can start/restart:
//
// 1. A client to the provider was never created, i.e. a new consumer chain is started for the first time.
// 2. A consumer chain restarts after a client to the provider was created, but the CCV channel handshake is still in progress
// 3. A consumer chain restarts after the CCV channel handshake was completed.
func (k Keeper) InitGenesis(ctx sdk.Context, state *types.GenesisState) []abci.ValidatorUpdate {
// PreCCV is true during the process of a standalone to consumer changeover.
// At the PreCCV point in the process, the standalone chain has just been upgraded to include
// the consumer ccv module, but the standalone staking keeper is still managing the validator set.
// Once the provider validator set starts validating blocks, the consumer CCV module
// will take over proof of stake capabilities, but the standalone staking keeper will
// stick around for slashing/jailing purposes.
if state.PreCCV {
k.SetPreCCVTrue(ctx)
k.MarkAsPrevStandaloneChain(ctx)
k.SetInitialValSet(ctx, state.Provider.InitialValSet)
}
k.SetInitGenesisHeight(ctx, ctx.BlockHeight()) // Usually 0, but not the case for changeover chains
k.SetParams(ctx, state.Params)
// TODO: Remove enabled flag and find a better way to setup integration tests
// See: https://github.com/cosmos/interchain-security/issues/339
if !state.Params.Enabled {
return nil
}
k.SetPort(ctx, ccv.ConsumerPortID)
// Only try to bind to port if it is not already bound, since we may already own
// port capability from capability InitGenesis
if !k.IsBound(ctx, ccv.ConsumerPortID) {
// transfer module binds to the transfer port on InitChain
// and claims the returned capability
err := k.BindPort(ctx, ccv.ConsumerPortID)
if err != nil {
// If the binding fails, the chain MUST NOT start
panic(fmt.Sprintf("could not claim port capability: %v", err))
}
}
// initialValSet is checked in NewChain case by ValidateGenesis
// start a new chain
if state.NewChain {
// create the provider client in InitGenesis for new consumer chain. CCV Handshake must be established with this client id.
clientID, err := k.clientKeeper.CreateClient(ctx, state.Provider.ClientState, state.Provider.ConsensusState)
if err != nil {
// If the client creation fails, the chain MUST NOT start
panic(err)
}
// set provider client id.
k.SetProviderClientID(ctx, clientID)
// set default value for valset update ID
k.SetHeightValsetUpdateID(ctx, uint64(ctx.BlockHeight()), uint64(0))
} else {
// chain restarts with the CCV channel established
if state.ProviderChannelId != "" {
// set provider channel ID
k.SetProviderChannel(ctx, state.ProviderChannelId)
// set outstanding downtime slashing requests
for _, od := range state.OutstandingDowntimeSlashing {
consAddr, err := sdk.ConsAddressFromBech32(od.ValidatorConsensusAddress)
if err != nil {
panic(err)
}
k.SetOutstandingDowntime(ctx, consAddr)
}
// set last transmission block height
k.SetLastTransmissionBlockHeight(ctx, state.LastTransmissionBlockHeight)
}
// Set pending consumer packets, using the depreciated ConsumerPacketDataList type
// that exists for genesis.
// note that the list includes pending mature VSC packet only if the handshake is completed
for _, packet := range state.PendingConsumerPackets.List {
k.AppendPendingPacket(ctx, packet.Type, packet.Data)
}
// set height to valset update id mapping
for _, h2v := range state.HeightToValsetUpdateId {
k.SetHeightValsetUpdateID(ctx, h2v.Height, h2v.ValsetUpdateId)
}
// set provider client id
k.SetProviderClientID(ctx, state.ProviderClientId)
}
if state.PreCCV {
return []abci.ValidatorUpdate{}
}
// populate cross chain validators states with initial valset
k.ApplyCCValidatorChanges(ctx, state.Provider.InitialValSet)
return state.Provider.InitialValSet
}
// ExportGenesis returns the CCV consumer module's exported genesis
func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *types.GenesisState) {
params := k.GetConsumerParams(ctx)
if !params.Enabled {
return types.DefaultGenesisState()
}
// export the current validator set
valset := k.MustGetCurrentValidatorsAsABCIUpdates(ctx)
// export pending packets using the depreciated ConsumerPacketDataList type
pendingPackets := k.GetPendingPackets(ctx)
pendingPacketsDepreciated := types.ConsumerPacketDataList{}
pendingPacketsDepreciated.List = append(pendingPacketsDepreciated.List, pendingPackets...)
// export all the states created after a provider channel got established
if channelID, ok := k.GetProviderChannel(ctx); ok {
clientID, found := k.GetProviderClientID(ctx)
if !found {
// This should never happen
panic("provider client does not exist although provider channel does exist")
}
genesis = types.NewRestartGenesisState(
clientID,
channelID,
valset,
k.GetAllHeightToValsetUpdateIDs(ctx),
pendingPacketsDepreciated,
k.GetAllOutstandingDowntimes(ctx),
k.GetLastTransmissionBlockHeight(ctx),
params,
)
} else {
clientID, ok := k.GetProviderClientID(ctx)
// if provider clientID and channelID don't exist on the consumer chain,
// then CCV protocol is disabled for this chain return a default genesis state
if !ok {
return types.DefaultGenesisState()
}
// export client states and pending slashing requests into a new chain genesis
genesis = types.NewRestartGenesisState(
clientID,
"",
valset,
k.GetAllHeightToValsetUpdateIDs(ctx),
pendingPacketsDepreciated,
nil,
types.LastTransmissionBlockHeight{},
params,
)
}
return genesis
}