-
Notifications
You must be signed in to change notification settings - Fork 580
/
genesis.go
153 lines (130 loc) · 5.66 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
package v100
import (
"bytes"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/ibc-go/modules/core/02-client/types"
host "github.com/cosmos/ibc-go/modules/core/24-host"
"github.com/cosmos/ibc-go/modules/core/exported"
ibctmtypes "github.com/cosmos/ibc-go/modules/light-clients/07-tendermint/types"
)
// MigrateGenesis accepts exported v1.0.0 IBC client genesis file and migrates it to:
//
// - Update solo machine client state protobuf definition (v1 to v2)
// - Remove all solo machine consensus states
// - Remove all expired tendermint consensus states
// - Adds ProcessedHeight and Iteration keys for unexpired tendermint consensus states
func MigrateGenesis(cdc codec.BinaryCodec, clientGenState *types.GenesisState, genesisBlockTime time.Time, selfHeight exported.Height) (*types.GenesisState, error) {
// To prune the consensus states, we will create new clientsConsensus
// and clientsMetadata. These slices will be filled up with consensus states
// which should not be pruned. No solo machine consensus states should be added
// and only unexpired consensus states for tendermint clients will be added.
// The metadata keys for unexpired consensus states will be added to clientsMetadata
var (
clientsConsensus []types.ClientConsensusStates
clientsMetadata []types.IdentifiedGenesisMetadata
)
for i, client := range clientGenState.Clients {
clientType, _, err := types.ParseClientIdentifier(client.ClientId)
if err != nil {
return nil, err
}
// update solo machine client state defintions
if clientType == exported.Solomachine {
clientState := &ClientState{}
if err := cdc.Unmarshal(client.ClientState.Value, clientState); err != nil {
return nil, sdkerrors.Wrap(err, "failed to unmarshal client state bytes into solo machine client state")
}
updatedClientState := migrateSolomachine(clientState)
any, err := types.PackClientState(updatedClientState)
if err != nil {
return nil, err
}
clientGenState.Clients[i] = types.IdentifiedClientState{
ClientId: client.ClientId,
ClientState: any,
}
}
// iterate consensus states by client
for _, clientConsensusStates := range clientGenState.ClientsConsensus {
// look for consensus states for the current client
if clientConsensusStates.ClientId == client.ClientId {
switch clientType {
case exported.Solomachine:
// remove all consensus states for the solo machine
// do not add to new clientsConsensus
case exported.Tendermint:
// only add non expired consensus states to new clientsConsensus
tmClientState, ok := client.ClientState.GetCachedValue().(*ibctmtypes.ClientState)
if !ok {
return nil, types.ErrInvalidClient
}
// collect unexpired consensus states
var unexpiredConsensusStates []types.ConsensusStateWithHeight
for _, consState := range clientConsensusStates.ConsensusStates {
tmConsState := consState.ConsensusState.GetCachedValue().(*ibctmtypes.ConsensusState)
if !tmClientState.IsExpired(tmConsState.Timestamp, genesisBlockTime) {
unexpiredConsensusStates = append(unexpiredConsensusStates, consState)
}
}
// if we found at least one unexpired consensus state, create a clientConsensusState
// and add it to clientsConsensus
if len(unexpiredConsensusStates) != 0 {
clientsConsensus = append(clientsConsensus, types.ClientConsensusStates{
ClientId: client.ClientId,
ConsensusStates: unexpiredConsensusStates,
})
}
// collect metadata for unexpired consensus states
var clientMetadata []types.GenesisMetadata
// remove all expired tendermint consensus state metadata by adding only
// unexpired consensus state metadata
for _, consState := range unexpiredConsensusStates {
for _, identifiedGenMetadata := range clientGenState.ClientsMetadata {
// look for metadata for current client
if identifiedGenMetadata.ClientId == client.ClientId {
// obtain height for consensus state being pruned
height := consState.Height
// iterate through metadata and find metadata for current unexpired height
// only unexpired consensus state metadata should be added
for _, metadata := range identifiedGenMetadata.ClientMetadata {
// the previous version of IBC only contained the processed time metadata
// if we find the processed time metadata for an unexpired height, add the
// iteration key and processed height keys.
if bytes.Equal(metadata.Key, ibctmtypes.ProcessedTimeKey(height)) {
clientMetadata = append(clientMetadata,
// set the processed height using the current self height
// this is safe, it may cause delays in packet processing if there
// is a non zero connection delay time
types.GenesisMetadata{
Key: ibctmtypes.ProcessedHeightKey(height),
Value: []byte(selfHeight.String()),
},
metadata, // processed time
types.GenesisMetadata{
Key: ibctmtypes.IterationKey(height),
Value: host.ConsensusStateKey(height),
})
}
}
}
}
}
// if we have metadata for unexipred consensus states, add it to consensusMetadata
if len(clientMetadata) != 0 {
clientsMetadata = append(clientsMetadata, types.IdentifiedGenesisMetadata{
ClientId: client.ClientId,
ClientMetadata: clientMetadata,
})
}
default:
break
}
}
}
}
clientGenState.ClientsConsensus = clientsConsensus
clientGenState.ClientsMetadata = clientsMetadata
return clientGenState, nil
}