97 lines
2.8 KiB
Go
97 lines
2.8 KiB
Go
package types
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/cosmos/cosmos-sdk/x/bank/exported"
|
|
)
|
|
|
|
var _ exported.GenesisBalance = (*Balance)(nil)
|
|
|
|
// GetAddress returns the account address of the Balance object.
|
|
func (b Balance) GetAddress() sdk.AccAddress {
|
|
addr, err := sdk.AccAddressFromBech32(b.Address)
|
|
if err != nil {
|
|
panic(fmt.Errorf("couldn't convert %q to account address: %v", b.Address, err))
|
|
}
|
|
|
|
return addr
|
|
}
|
|
|
|
// GetCoins returns the account coins of the Balance object.
|
|
func (b Balance) GetCoins() sdk.Coins {
|
|
return b.Coins
|
|
}
|
|
|
|
// Validate checks for address and coins correctness.
|
|
func (b Balance) Validate() error {
|
|
if _, err := sdk.AccAddressFromBech32(b.Address); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := b.Coins.Validate(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type balanceByAddress struct {
|
|
addresses []sdk.AccAddress
|
|
balances []Balance
|
|
}
|
|
|
|
func (b balanceByAddress) Len() int { return len(b.addresses) }
|
|
func (b balanceByAddress) Less(i, j int) bool {
|
|
return bytes.Compare(b.addresses[i], b.addresses[j]) < 0
|
|
}
|
|
func (b balanceByAddress) Swap(i, j int) {
|
|
b.addresses[i], b.addresses[j] = b.addresses[j], b.addresses[i]
|
|
b.balances[i], b.balances[j] = b.balances[j], b.balances[i]
|
|
}
|
|
|
|
// SanitizeGenesisBalances sorts addresses and coin sets.
|
|
func SanitizeGenesisBalances(balances []Balance) []Balance {
|
|
// Given that this function sorts balances, using the standard library's
|
|
// Quicksort based algorithms, we have algorithmic complexities of:
|
|
// * Best case: O(nlogn)
|
|
// * Worst case: O(n^2)
|
|
// The comparator used MUST be cheap to use lest we incur expenses like we had
|
|
// before whereby sdk.AccAddressFromBech32, which is a very expensive operation
|
|
// compared n * n elements yet discarded computations each time, as per:
|
|
// https://github.com/cosmos/cosmos-sdk/issues/7766#issuecomment-786671734
|
|
|
|
// 1. Retrieve the address equivalents for each Balance's address.
|
|
addresses := make([]sdk.AccAddress, len(balances))
|
|
for i := range balances {
|
|
addr, _ := sdk.AccAddressFromBech32(balances[i].Address)
|
|
addresses[i] = addr
|
|
}
|
|
|
|
// 2. Sort balances.
|
|
sort.Sort(balanceByAddress{addresses: addresses, balances: balances})
|
|
|
|
return balances
|
|
}
|
|
|
|
// GenesisBalancesIterator implements genesis account iteration.
|
|
type GenesisBalancesIterator struct{}
|
|
|
|
// IterateGenesisBalances iterates over all the genesis balances found in
|
|
// appGenesis and invokes a callback on each genesis account. If any call
|
|
// returns true, iteration stops.
|
|
func (GenesisBalancesIterator) IterateGenesisBalances(
|
|
cdc codec.JSONCodec, appState map[string]json.RawMessage, cb func(exported.GenesisBalance) (stop bool),
|
|
) {
|
|
for _, balance := range GetGenesisStateFromAppState(cdc, appState).Balances {
|
|
if cb(balance) {
|
|
break
|
|
}
|
|
}
|
|
}
|