-
Notifications
You must be signed in to change notification settings - Fork 50
/
export.go
147 lines (121 loc) · 4.71 KB
/
export.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
package app
import (
"encoding/json"
"log"
abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/staking"
)
// ExportAppStateAndValidators exports the application state for a genesis file.
func (app *CertiKApp) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteList []string) (
appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) {
ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()})
if forZeroHeight {
app.prepForZeroHeightGenesis(ctx, jailWhiteList)
}
genState := app.mm.ExportGenesis(ctx)
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
if err != nil {
return nil, nil, err
}
validators = staking.WriteValidators(ctx, app.stakingKeeper.Keeper)
return appState, validators, nil
}
// prepForZeroHeightGenesis prepares for fresh start at zero height.
// NOTE: Zero-height genesis is a temporary feature which will be deprecated
// in favor of export at a block height.
func (app *CertiKApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []string) {
whiteListMap := make(map[string]bool)
for _, addr := range jailWhiteList {
if _, err := sdk.ValAddressFromBech32(addr); err != nil {
log.Fatal(err)
}
whiteListMap[addr] = true
}
/* Handle fee distribution state. */
// withdraw all validator commission
app.stakingKeeper.IterateValidators(ctx, func(_ int64, val staking.ValidatorI) (stop bool) {
app.distrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator())
return false
})
// withdraw all delegator rewards
dels := app.stakingKeeper.GetAllDelegations(ctx)
for _, delegation := range dels {
app.distrKeeper.WithdrawDelegationRewards(ctx, delegation.DelegatorAddress, delegation.ValidatorAddress)
}
// clear validator slash events and historical rewards
app.distrKeeper.DeleteAllValidatorSlashEvents(ctx)
app.distrKeeper.DeleteAllValidatorHistoricalRewards(ctx)
// set context height to zero
height := ctx.BlockHeight()
ctx = ctx.WithBlockHeight(0)
// reinitialize all validators
app.stakingKeeper.IterateValidators(ctx, func(_ int64, val staking.ValidatorI) (stop bool) {
// donate any unwithdrawn outstanding reward fraction tokens to the community pool
scraps := app.distrKeeper.GetValidatorOutstandingRewards(ctx, val.GetOperator())
feePool := app.distrKeeper.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(scraps...)
app.distrKeeper.SetFeePool(ctx, feePool)
app.distrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator())
return false
})
// reinitialize all delegations
for _, del := range dels {
app.distrKeeper.Hooks().BeforeDelegationCreated(ctx, del.DelegatorAddress, del.ValidatorAddress)
app.distrKeeper.Hooks().AfterDelegationModified(ctx, del.DelegatorAddress, del.ValidatorAddress)
}
// reset context height
ctx = ctx.WithBlockHeight(height)
/* Handle staking state. */
// iterate through redelegations, reset creation height
app.stakingKeeper.IterateRedelegations(ctx, func(_ int64, red staking.Redelegation) (stop bool) {
for _, e := range red.Entries {
e.CreationHeight = 0
}
app.stakingKeeper.SetRedelegation(ctx, red)
return false
})
// iterate through unbonding delegations, reset creation height
app.stakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd staking.UnbondingDelegation) (stop bool) {
for _, e := range ubd.Entries {
e.CreationHeight = 0
}
app.stakingKeeper.SetUnbondingDelegation(ctx, ubd)
return false
})
// iterate through validators by power descending, reset bond heights, and
// update bond intra-tx counters
store := ctx.KVStore(app.keys[staking.StoreKey])
iter := sdk.KVStoreReversePrefixIterator(store, staking.ValidatorsKey)
counter := int16(0)
var valConsAddrs []sdk.ConsAddress
for ; iter.Valid(); iter.Next() {
addr := sdk.ValAddress(iter.Key()[1:])
validator, found := app.stakingKeeper.GetValidator(ctx, addr)
if !found {
panic("expected validator, not found")
}
validator.UnbondingHeight = 0
valConsAddrs = append(valConsAddrs, validator.ConsAddress())
if (len(jailWhiteList) > 0) && !whiteListMap[addr.String()] {
validator.Jailed = true
}
app.stakingKeeper.SetValidator(ctx, validator)
counter++
}
iter.Close()
_ = app.stakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
/* Handle slashing state. */
// reset start height on signing infos
app.slashingKeeper.IterateValidatorSigningInfos(
ctx,
func(addr sdk.ConsAddress, info slashing.ValidatorSigningInfo) (stop bool) {
info.StartHeight = 0
app.slashingKeeper.SetValidatorSigningInfo(ctx, addr, info)
return false
},
)
}