Fix x/bank genesis non-determinism (#6940)

* Sort coins in x/bank genesis

* Sort address before looping

* GetAccountsBalances

Co-authored-by: Federico Kunze <federico.kunze94@gmail.com>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
SaReN 2020-08-06 14:40:07 +05:30 committed by GitHub
parent e3391ff447
commit ba140c90f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 22 deletions

View File

@ -35,26 +35,10 @@ func (k BaseKeeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) {
// ExportGenesis returns the bank module's genesis state. // ExportGenesis returns the bank module's genesis state.
func (k BaseKeeper) ExportGenesis(ctx sdk.Context) types.GenesisState { func (k BaseKeeper) ExportGenesis(ctx sdk.Context) types.GenesisState {
balancesSet := make(map[string]sdk.Coins) return types.NewGenesisState(
k.GetParams(ctx),
k.IterateAllBalances(ctx, func(addr sdk.AccAddress, balance sdk.Coin) bool { k.GetAccountsBalances(ctx),
balancesSet[addr.String()] = balancesSet[addr.String()].Add(balance) k.GetSupply(ctx).GetTotal(),
return false k.GetAllDenomMetaData(ctx),
}) )
balances := []types.Balance{}
for addrStr, coins := range balancesSet {
addr, err := sdk.AccAddressFromBech32(addrStr)
if err != nil {
panic(fmt.Errorf("failed to convert address from string: %w", err))
}
balances = append(balances, types.Balance{
Address: addr,
Coins: coins,
})
}
return types.NewGenesisState(k.GetParams(ctx), balances, k.GetSupply(ctx).GetTotal(), k.GetAllDenomMetaData(ctx))
} }

View File

@ -22,6 +22,7 @@ type ViewKeeper interface {
HasBalance(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coin) bool HasBalance(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coin) bool
GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
GetAccountsBalances(ctx sdk.Context) []types.Balance
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
@ -67,6 +68,32 @@ func (k BaseViewKeeper) GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk
return balances.Sort() return balances.Sort()
} }
// GetAccountsBalances returns all the accounts balances from the store.
func (k BaseViewKeeper) GetAccountsBalances(ctx sdk.Context) []types.Balance {
balances := make([]types.Balance, 0)
mapAddressToBalancesIdx := make(map[string]int)
k.IterateAllBalances(ctx, func(addr sdk.AccAddress, balance sdk.Coin) bool {
idx, ok := mapAddressToBalancesIdx[addr.String()]
if ok {
// address is already on the set of accounts balances
balances[idx].Coins = balances[idx].Coins.Add(balance)
balances[idx].Coins.Sort()
return false
}
accountBalance := types.Balance{
Address: addr,
Coins: sdk.NewCoins(balance),
}
balances = append(balances, accountBalance)
mapAddressToBalancesIdx[addr.String()] = len(balances) - 1
return false
})
return balances
}
// GetBalance returns the balance of a specific denomination for a given account // GetBalance returns the balance of a specific denomination for a given account
// by address. // by address.
func (k BaseViewKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { func (k BaseViewKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin {