Merge PR #5572: ADR 004 Implementation

This commit is contained in:
Alexander Bezobchuk
2020-01-30 16:31:16 -05:00
committed by GitHub
parent b669ac5eaa
commit 6890feb3d2
133 changed files with 3057 additions and 1931 deletions
@@ -5,6 +5,7 @@
- 2020-01-08: Initial version
- 2020-01-09: Alterations to handle vesting accounts
- 2020-01-14: Updates from review feedback
- 2020-01-30: Updates from implementation
## Context
@@ -18,35 +19,74 @@ Balances shall be stored per-account & per-denomination under a denomination- an
### Account interface (x/auth)
`GetCoins()` and `SetCoins()` will be removed from the account interface, since coin balances will now be stored in & managed by the bank module.
`GetCoins()` and `SetCoins()` will be removed from the account interface, since coin balances will
now be stored in & managed by the bank module.
`SpendableCoinsVestingAccount()` and `TrackDelegation()` will be altered to take a bank keeper and a denomination as two additional arguments, which will be used to lookup the balances from the base account as necessary.
The vesting account interface will replace `SpendableCoins` in favor of `LockedCoins` which does
not require the account balance anymore. In addition, `TrackDelegation()` will now accept the
account balance of all tokens denominated in the vesting balance instead of loading the entire
account balance.
Vesting accounts will continue to store original vesting, delegated free, and delegated vesting coins (which is safe since these cannot contain arbitrary denominations).
Vesting accounts will continue to store original vesting, delegated free, and delegated
vesting coins (which is safe since these cannot contain arbitrary denominations).
### Bank keeper (x/bank)
`GetBalance(addr AccAddress, denom string) sdk.Coin` and `SetBalance(addr AccAddress, coin sdk.Coin)` methods will be added to the bank keeper to retrieve & set balances, respectively.
The following APIs will be added to the `x/bank` keeper:
Balances will be stored first by the address, then by the denomination (the reverse is also possible, but retrieval of all balances for a single account is presumed to be more frequent):
- `GetAllBalances(ctx Context, addr AccAddress) Coins`
- `GetBalance(ctx Context, addr AccAddress, denom string) Coin`
- `SetBalance(ctx Context, addr AccAddress, coin Coin)`
- `LockedCoins(ctx Context, addr AccAddress) Coins`
- `SpendableCoins(ctx Context, addr AccAddress) Coins`
Additional APIs may be added to facilitate iteration and auxiliary functionality not essential to
core functionality or persistence.
Balances will be stored first by the address, then by the denomination (the reverse is also possible,
but retrieval of all balances for a single account is presumed to be more frequent):
```golang
func BalanceKey(addr sdk.AccAddress, denom string) []byte {
return append(append(BalanceKeyPrefix, addr.Bytes()...), []byte(denom)...)
var BalancesPrefix = []byte("balances")
func (k Keeper) SetBalance(ctx Context, addr AccAddress, balance Coin) error {
if !balance.IsValid() {
return err
}
store := ctx.KVStore(k.storeKey)
balancesStore := prefix.NewStore(store, BalancesPrefix)
accountStore := prefix.NewStore(balancesStore, addr.Bytes())
bz := Marshal(balance)
accountStore.Set([]byte(balance.Denom), bz)
return nil
}
```
`DelegateCoins()` and `UndelegateCoins()` will be altered to take a single `sdk.Coin` (one denomination & amount) instead of `sdk.Coins`, since they should only operate on one denomination. They will read balances directly instead of calling `GetCoins()` (which no longer exists).
This will result in the balances being indexed by the byte representation of
`balances/{address}/{denom}`.
`SubtractCoins()` and `AddCoins()` will be altered to read & write the balances directly instead of calling `GetCoins()` / `SetCoins()` (which no longer exist).
`DelegateCoins()` and `UndelegateCoins()` will be altered to only load each individual
account balance by denomination found in the (un)delegation amount. As a result,
any mutations to the account balance by will made by denomination.
`trackDelegation()` and `trackUndelegation()` will be altered to read & write the balances directly instead of calling `GetCoins()` / `SetCoins()` (which no longer exist).
`SubtractCoins()` and `AddCoins()` will be altered to read & write the balances
directly instead of calling `GetCoins()` / `SetCoins()` (which no longer exist).
External APIs will need to scan all balances under an account to retain backwards-compatibility - additional methods should be added to fetch a balance for a single denomination only.
`trackDelegation()` and `trackUndelegation()` will be altered to no longer update
account balances.
External APIs will need to scan all balances under an account to retain backwards-compatibility. It
is advised that these APIs use `GetBalance` and `SetBalance` instead of `GetAllBalances` when
possible as to not load the entire account balance.
### Supply module
The supply module, in order to implement the total supply invariant, will now need to scan all accounts & call `GetBalance` using the `x/bank` Keeper for the denomination in question, then sum the balances and check that they match the expected total supply.
The supply module, in order to implement the total supply invariant, will now need
to scan all accounts & call `GetAllBalances` using the `x/bank` Keeper, then sum
the balances and check that they match the expected total supply.
## Status
@@ -56,11 +96,14 @@ Proposed.
### Positive
- O(1) reads & writes of balances (with respect to the number of denominations for which an account has non-zero balances)
- O(1) reads & writes of balances (with respect to the number of denominations for
which an account has non-zero balances). Note, this does not relate to the actual
I/O cost, rather the total number of direct reads needed.
### Negative
- Slighly less efficient reads/writes when reading & writing all balances of a single account in a transaction.
- Slightly less efficient reads/writes when reading & writing all balances of a
single account in a transaction.
### Neutral
@@ -68,6 +111,6 @@ None in particular.
## References
Ref https://github.com/cosmos/cosmos-sdk/issues/4982
Ref https://github.com/cosmos/cosmos-sdk/issues/5467
Ref https://github.com/cosmos/cosmos-sdk/issues/5492
- Ref: https://github.com/cosmos/cosmos-sdk/issues/4982
- Ref: https://github.com/cosmos/cosmos-sdk/issues/5467
- Ref: https://github.com/cosmos/cosmos-sdk/issues/5492