refactor(gov)!: use collections for deposit state management (#16127)
Co-authored-by: unknown unknown <unknown@unknown>
This commit is contained in:
parent
b8e15a7930
commit
71468d2d5a
@ -196,6 +196,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
* (types/math) [#16040](https://github.com/cosmos/cosmos-sdk/pull/16040) Remove unused aliases in math.go
|
||||
* (x/gov) [#16106](https://github.com/cosmos/cosmos-sdk/pull/16106) Remove gRPC query methods from Keeper
|
||||
* (x/gov) [#16118](https://github.com/cosmos/cosmos-sdk/pull/16118/) Use collections for constituion and params state management.
|
||||
* (x/gov) [](https://github.com/cosmos/cosmos-sdk/pull/16127) Use collections for deposit management:
|
||||
- The following methods are removed from the gov keeper: `GetDeposit`, `GetAllDeposits`, `IterateAllDeposits`.
|
||||
- The following functions are removed from the gov types: `DepositKey`, `DepositsKey`.
|
||||
|
||||
### Client Breaking Changes
|
||||
|
||||
|
||||
@ -35,6 +35,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
* [#16074](https://github.com/cosmos/cosmos-sdk/pull/16074) – makes the generic Collection interface public, still highly unstable.
|
||||
|
||||
### API Breaking
|
||||
|
||||
* [#16127](https://github.com/cosmos/cosmos-sdk/pull/16127) – In the `Walk` method the call back function being passed is allowed to error.
|
||||
|
||||
## [v0.1.0](https://github.com/cosmos/cosmos-sdk/releases/tag/collections%2Fv0.1.0)
|
||||
|
||||
Collections `v0.1.0` is released! Check out the [docs](https://docs.cosmos.network/main/packages/collections) to know how to use the APIs.
|
||||
@ -93,7 +93,7 @@ func (m *IndexedMap[PrimaryKey, Value, Idx]) Remove(ctx context.Context, pk Prim
|
||||
}
|
||||
|
||||
// Walk applies the same semantics as Map.Walk.
|
||||
func (m *IndexedMap[PrimaryKey, Value, Idx]) Walk(ctx context.Context, ranger Ranger[PrimaryKey], walkFunc func(key PrimaryKey, value Value) bool) error {
|
||||
func (m *IndexedMap[PrimaryKey, Value, Idx]) Walk(ctx context.Context, ranger Ranger[PrimaryKey], walkFunc func(key PrimaryKey, value Value) (stop bool, err error)) error {
|
||||
return m.m.Walk(ctx, ranger, walkFunc)
|
||||
}
|
||||
|
||||
|
||||
@ -82,9 +82,9 @@ func (m *Multi[ReferenceKey, PrimaryKey, Value]) Iterate(ctx context.Context, ra
|
||||
func (m *Multi[ReferenceKey, PrimaryKey, Value]) Walk(
|
||||
ctx context.Context,
|
||||
ranger collections.Ranger[collections.Pair[ReferenceKey, PrimaryKey]],
|
||||
walkFunc func(indexingKey ReferenceKey, indexedKey PrimaryKey) bool,
|
||||
walkFunc func(indexingKey ReferenceKey, indexedKey PrimaryKey) (stop bool, err error),
|
||||
) error {
|
||||
return m.refKeys.Walk(ctx, ranger, func(key collections.Pair[ReferenceKey, PrimaryKey]) bool {
|
||||
return m.refKeys.Walk(ctx, ranger, func(key collections.Pair[ReferenceKey, PrimaryKey]) (bool, error) {
|
||||
return walkFunc(key.K1(), key.K2())
|
||||
})
|
||||
}
|
||||
|
||||
@ -67,9 +67,9 @@ func (i *ReversePair[K1, K2, Value]) Unreference(ctx context.Context, pk collect
|
||||
func (i *ReversePair[K1, K2, Value]) Walk(
|
||||
ctx context.Context,
|
||||
ranger collections.Ranger[collections.Pair[K2, K1]],
|
||||
walkFunc func(indexingKey K2, indexedKey K1) bool,
|
||||
walkFunc func(indexingKey K2, indexedKey K1) (stop bool, err error),
|
||||
) error {
|
||||
return i.refKeys.Walk(ctx, ranger, func(key collections.Pair[K2, K1]) bool {
|
||||
return i.refKeys.Walk(ctx, ranger, func(key collections.Pair[K2, K1]) (bool, error) {
|
||||
return walkFunc(key.K1(), key.K2())
|
||||
})
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ func (i *Unique[ReferenceKey, PrimaryKey, Value]) Iterate(ctx context.Context, r
|
||||
func (i *Unique[ReferenceKey, PrimaryKey, Value]) Walk(
|
||||
ctx context.Context,
|
||||
ranger collections.Ranger[ReferenceKey],
|
||||
walkFunc func(indexingKey ReferenceKey, indexedKey PrimaryKey) bool,
|
||||
walkFunc func(indexingKey ReferenceKey, indexedKey PrimaryKey) (stop bool, err error),
|
||||
) error {
|
||||
return i.refKeys.Walk(ctx, ranger, walkFunc)
|
||||
}
|
||||
|
||||
@ -175,14 +175,24 @@ func TestWalk(t *testing.T) {
|
||||
}
|
||||
|
||||
u := uint64(0)
|
||||
err = m.Walk(ctx, nil, func(key, value uint64) bool {
|
||||
err = m.Walk(ctx, nil, func(key, value uint64) (bool, error) {
|
||||
if key == 5 {
|
||||
return true
|
||||
return true, nil
|
||||
}
|
||||
require.Equal(t, u, key)
|
||||
require.Equal(t, u, value)
|
||||
u++
|
||||
return false
|
||||
return false, nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
sentinelErr := fmt.Errorf("sentinel error")
|
||||
err = m.Walk(ctx, nil, func(key, value uint64) (stop bool, err error) {
|
||||
require.LessOrEqual(t, key, uint64(3)) // asserts that after the number three we stop
|
||||
if key == 3 {
|
||||
return false, sentinelErr
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
require.ErrorIs(t, err, sentinelErr) // asserts correct error propagation
|
||||
}
|
||||
|
||||
@ -53,8 +53,8 @@ func (k KeySet[K]) IterateRaw(ctx context.Context, start, end []byte, order Orde
|
||||
|
||||
// Walk provides the same functionality as Map.Walk, but callbacks the walk
|
||||
// function only with the key.
|
||||
func (k KeySet[K]) Walk(ctx context.Context, ranger Ranger[K], walkFunc func(key K) bool) error {
|
||||
return (Map[K, NoValue])(k).Walk(ctx, ranger, func(key K, value NoValue) bool { return walkFunc(key) })
|
||||
func (k KeySet[K]) Walk(ctx context.Context, ranger Ranger[K], walkFunc func(key K) (stop bool, err error)) error {
|
||||
return (Map[K, NoValue])(k).Walk(ctx, ranger, func(key K, value NoValue) (bool, error) { return walkFunc(key) })
|
||||
}
|
||||
|
||||
func (k KeySet[K]) KeyCodec() codec.KeyCodec[K] { return (Map[K, NoValue])(k).KeyCodec() }
|
||||
|
||||
@ -127,7 +127,7 @@ func (m Map[K, V]) Iterate(ctx context.Context, ranger Ranger[K]) (Iterator[K, V
|
||||
// walk function with the decoded key and value. If the callback function
|
||||
// returns true then the walking is stopped.
|
||||
// A nil ranger equals to walking over the entire key and value set.
|
||||
func (m Map[K, V]) Walk(ctx context.Context, ranger Ranger[K], walkFunc func(K, V) bool) error {
|
||||
func (m Map[K, V]) Walk(ctx context.Context, ranger Ranger[K], walkFunc func(key K, value V) (stop bool, err error)) error {
|
||||
iter, err := m.Iterate(ctx, ranger)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -139,7 +139,11 @@ func (m Map[K, V]) Walk(ctx context.Context, ranger Ranger[K], walkFunc func(K,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if walkFunc(kv.Key, kv.Value) {
|
||||
stop, err := walkFunc(kv.Key, kv.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stop {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,8 +155,6 @@ require (
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
replace cosmossdk.io/collections => ../../collections
|
||||
|
||||
// Fix upstream GHSA-h395-qcrw-5vmq and GHSA-3vp4-m3rf-835h vulnerabilities.
|
||||
// TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409
|
||||
// TODO investigate if we can outright delete this dependency, otherwise go install won't work :(
|
||||
|
||||
@ -37,6 +37,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
cosmossdk.io/api v0.4.1 h1:0ikaYM6GyxTYYcfBiyR8YnLCfhNnhKpEFnaSepCTmqg=
|
||||
cosmossdk.io/api v0.4.1/go.mod h1:jR7k5ok90LxW2lFUXvd8Vpo/dr4PpiyVegxdm7b1ZdE=
|
||||
cosmossdk.io/collections v0.1.0 h1:nzJGeiq32KnZroSrhB6rPifw4I85Cgmzw/YAmr4luv8=
|
||||
cosmossdk.io/collections v0.1.0/go.mod h1:xbauc0YsbUF8qKMVeBZl0pFCunxBIhKN/WlxpZ3lBuo=
|
||||
cosmossdk.io/core v0.7.0 h1:GFss3qt2P9p23Cz24NnqLkslzb8n+B75A24x1JgJJp0=
|
||||
cosmossdk.io/core v0.7.0/go.mod h1:36hP0ZH/8ipsjzfcp0yKU4bqQXUGhS0/m1krWFCtwCc=
|
||||
cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw=
|
||||
|
||||
@ -2,8 +2,11 @@ package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/math"
|
||||
@ -256,9 +259,12 @@ func (k BaseKeeper) GetAllDenomMetaData(ctx context.Context) []types.Metadata {
|
||||
// provides the metadata to a callback. If true is returned from the
|
||||
// callback, iteration is halted.
|
||||
func (k BaseKeeper) IterateAllDenomMetaData(ctx context.Context, cb func(types.Metadata) bool) {
|
||||
_ = k.BaseViewKeeper.DenomMetadata.Walk(ctx, nil, func(_ string, metadata types.Metadata) bool {
|
||||
return cb(metadata)
|
||||
err := k.BaseViewKeeper.DenomMetadata.Walk(ctx, nil, func(_ string, metadata types.Metadata) (stop bool, err error) {
|
||||
return cb(metadata), nil
|
||||
})
|
||||
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetDenomMetaData sets the denominations metadata
|
||||
@ -474,7 +480,10 @@ func (k BaseKeeper) trackUndelegation(ctx context.Context, addr sdk.AccAddress,
|
||||
// with the balance of each coin.
|
||||
// The iteration stops if the callback returns true.
|
||||
func (k BaseViewKeeper) IterateTotalSupply(ctx context.Context, cb func(sdk.Coin) bool) {
|
||||
_ = k.Supply.Walk(ctx, nil, func(s string, m math.Int) bool {
|
||||
return cb(sdk.NewCoin(s, m))
|
||||
err := k.Supply.Walk(ctx, nil, func(s string, m math.Int) (bool, error) {
|
||||
return cb(sdk.NewCoin(s, m)), nil
|
||||
})
|
||||
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,7 +376,12 @@ func (k BaseSendKeeper) DeleteSendEnabled(ctx context.Context, denoms ...string)
|
||||
|
||||
// IterateSendEnabledEntries iterates over all the SendEnabled entries.
|
||||
func (k BaseSendKeeper) IterateSendEnabledEntries(ctx context.Context, cb func(denom string, sendEnabled bool) bool) {
|
||||
_ = k.SendEnabled.Walk(ctx, nil, cb)
|
||||
err := k.SendEnabled.Walk(ctx, nil, func(key string, value bool) (stop bool, err error) {
|
||||
return cb(key, value), nil
|
||||
})
|
||||
if err != nil && !errorsmod.IsOf(err, collections.ErrInvalidIterator) {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllSendEnabledEntries gets all the SendEnabled entries that are stored.
|
||||
|
||||
@ -157,10 +157,10 @@ func (k BaseViewKeeper) GetBalance(ctx context.Context, addr sdk.AccAddress, den
|
||||
// provides the token balance to a callback. If true is returned from the
|
||||
// callback, iteration is halted.
|
||||
func (k BaseViewKeeper) IterateAccountBalances(ctx context.Context, addr sdk.AccAddress, cb func(sdk.Coin) bool) {
|
||||
err := k.Balances.Walk(ctx, collections.NewPrefixedPairRange[sdk.AccAddress, string](addr), func(key collections.Pair[sdk.AccAddress, string], value math.Int) bool {
|
||||
return cb(sdk.NewCoin(key.K2(), value))
|
||||
err := k.Balances.Walk(ctx, collections.NewPrefixedPairRange[sdk.AccAddress, string](addr), func(key collections.Pair[sdk.AccAddress, string], value math.Int) (stop bool, err error) {
|
||||
return cb(sdk.NewCoin(key.K2(), value)), nil
|
||||
})
|
||||
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) { // TODO(tip): is this the correct strategy
|
||||
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@ -169,10 +169,10 @@ func (k BaseViewKeeper) IterateAccountBalances(ctx context.Context, addr sdk.Acc
|
||||
// denominations that are provided to a callback. If true is returned from the
|
||||
// callback, iteration is halted.
|
||||
func (k BaseViewKeeper) IterateAllBalances(ctx context.Context, cb func(sdk.AccAddress, sdk.Coin) bool) {
|
||||
err := k.Balances.Walk(ctx, nil, func(key collections.Pair[sdk.AccAddress, string], value math.Int) bool {
|
||||
return cb(key.K1(), sdk.NewCoin(key.K2(), value))
|
||||
err := k.Balances.Walk(ctx, nil, func(key collections.Pair[sdk.AccAddress, string], value math.Int) (stop bool, err error) {
|
||||
return cb(key.K1(), sdk.NewCoin(key.K2(), value)), nil
|
||||
})
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,7 +34,10 @@ func InitGenesis(ctx sdk.Context, ak types.AccountKeeper, bk types.BankKeeper, k
|
||||
|
||||
var totalDeposits sdk.Coins
|
||||
for _, deposit := range data.Deposits {
|
||||
k.SetDeposit(ctx, *deposit)
|
||||
err := k.SetDeposit(ctx, *deposit)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
totalDeposits = totalDeposits.Add(deposit.Amount...)
|
||||
}
|
||||
|
||||
|
||||
@ -4,147 +4,55 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
|
||||
"cosmossdk.io/errors"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
)
|
||||
|
||||
// GetDeposit gets the deposit of a specific depositor on a specific proposal
|
||||
func (keeper Keeper) GetDeposit(ctx context.Context, proposalID uint64, depositorAddr sdk.AccAddress) (deposit v1.Deposit, err error) {
|
||||
store := keeper.storeService.OpenKVStore(ctx)
|
||||
bz, err := store.Get(types.DepositKey(proposalID, depositorAddr))
|
||||
if err != nil {
|
||||
return deposit, err
|
||||
}
|
||||
|
||||
if bz == nil {
|
||||
return deposit, types.ErrDepositNotFound
|
||||
}
|
||||
|
||||
err = keeper.cdc.Unmarshal(bz, &deposit)
|
||||
if err != nil {
|
||||
return deposit, err
|
||||
}
|
||||
|
||||
return deposit, nil
|
||||
}
|
||||
|
||||
// SetDeposit sets a Deposit to the gov store
|
||||
func (keeper Keeper) SetDeposit(ctx context.Context, deposit v1.Deposit) error {
|
||||
store := keeper.storeService.OpenKVStore(ctx)
|
||||
bz, err := keeper.cdc.Marshal(&deposit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
depositor, err := keeper.authKeeper.StringToBytes(deposit.Depositor)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return store.Set(types.DepositKey(deposit.ProposalId, depositor), bz)
|
||||
}
|
||||
|
||||
// GetAllDeposits returns all the deposits from the store
|
||||
func (keeper Keeper) GetAllDeposits(ctx context.Context) (deposits v1.Deposits, err error) {
|
||||
err = keeper.IterateAllDeposits(ctx, func(deposit v1.Deposit) error {
|
||||
deposits = append(deposits, &deposit)
|
||||
return nil
|
||||
})
|
||||
|
||||
return
|
||||
return keeper.Deposits.Set(ctx, collections.Join(deposit.ProposalId, sdk.AccAddress(depositor)), deposit)
|
||||
}
|
||||
|
||||
// GetDeposits returns all the deposits of a proposal
|
||||
func (keeper Keeper) GetDeposits(ctx context.Context, proposalID uint64) (deposits v1.Deposits, err error) {
|
||||
err = keeper.IterateDeposits(ctx, proposalID, func(deposit v1.Deposit) error {
|
||||
err = keeper.IterateDeposits(ctx, proposalID, func(_ collections.Pair[uint64, sdk.AccAddress], deposit v1.Deposit) (bool, error) {
|
||||
deposits = append(deposits, &deposit)
|
||||
return nil
|
||||
return false, nil
|
||||
})
|
||||
|
||||
return
|
||||
return deposits, err
|
||||
}
|
||||
|
||||
// DeleteAndBurnDeposits deletes and burns all the deposits on a specific proposal.
|
||||
func (keeper Keeper) DeleteAndBurnDeposits(ctx context.Context, proposalID uint64) error {
|
||||
store := keeper.storeService.OpenKVStore(ctx)
|
||||
|
||||
err := keeper.IterateDeposits(ctx, proposalID, func(deposit v1.Deposit) error {
|
||||
err := keeper.bankKeeper.BurnCoins(ctx, types.ModuleName, deposit.Amount)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
depositor, err := keeper.authKeeper.StringToBytes(deposit.Depositor)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = store.Delete(types.DepositKey(proposalID, depositor))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
coinsToBurn := sdk.NewCoins()
|
||||
err := keeper.IterateDeposits(ctx, proposalID, func(key collections.Pair[uint64, sdk.AccAddress], deposit v1.Deposit) (stop bool, err error) {
|
||||
coinsToBurn = coinsToBurn.Add(deposit.Amount...)
|
||||
return false, keeper.Deposits.Remove(ctx, key)
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// IterateAllDeposits iterates over all the stored deposits and performs a callback function.
|
||||
func (keeper Keeper) IterateAllDeposits(ctx context.Context, cb func(deposit v1.Deposit) error) error {
|
||||
store := keeper.storeService.OpenKVStore(ctx)
|
||||
iterator := storetypes.KVStorePrefixIterator(runtime.KVStoreAdapter(store), types.DepositsKeyPrefix)
|
||||
defer iterator.Close()
|
||||
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
var deposit v1.Deposit
|
||||
|
||||
err := keeper.cdc.Unmarshal(iterator.Value(), &deposit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cb(deposit)
|
||||
// exit early without error if cb returns ErrStopIterating
|
||||
if errors.IsOf(err, errors.ErrStopIterating) {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return keeper.bankKeeper.BurnCoins(ctx, types.ModuleName, coinsToBurn)
|
||||
}
|
||||
|
||||
// IterateDeposits iterates over all the proposals deposits and performs a callback function
|
||||
func (keeper Keeper) IterateDeposits(ctx context.Context, proposalID uint64, cb func(deposit v1.Deposit) error) error {
|
||||
store := keeper.storeService.OpenKVStore(ctx)
|
||||
iterator := storetypes.KVStorePrefixIterator(runtime.KVStoreAdapter(store), types.DepositsKey(proposalID))
|
||||
|
||||
defer iterator.Close()
|
||||
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
var deposit v1.Deposit
|
||||
err := keeper.cdc.Unmarshal(iterator.Value(), &deposit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cb(deposit)
|
||||
// exit early without error if cb returns ErrStopIterating
|
||||
if errors.IsOf(err, errors.ErrStopIterating) {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
func (keeper Keeper) IterateDeposits(ctx context.Context, proposalID uint64, cb func(key collections.Pair[uint64, sdk.AccAddress], value v1.Deposit) (bool, error)) error {
|
||||
rng := collections.NewPrefixedPairRange[uint64, sdk.AccAddress](proposalID)
|
||||
err := keeper.Deposits.Walk(ctx, rng, cb)
|
||||
if err != nil && !errors.IsOf(err, collections.ErrInvalidIterator) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -196,12 +104,12 @@ func (keeper Keeper) AddDeposit(ctx context.Context, proposalID uint64, deposito
|
||||
}
|
||||
|
||||
// Add or update deposit object
|
||||
deposit, err := keeper.GetDeposit(ctx, proposalID, depositorAddr)
|
||||
deposit, err := keeper.Deposits.Get(ctx, collections.Join(proposalID, depositorAddr))
|
||||
switch {
|
||||
case err == nil:
|
||||
// deposit exists
|
||||
deposit.Amount = sdk.NewCoins(deposit.Amount...).Add(depositAmount...)
|
||||
case errors.IsOf(err, types.ErrDepositNotFound):
|
||||
case errors.IsOf(err, collections.ErrNotFound):
|
||||
// deposit doesn't exist
|
||||
deposit = v1.NewDeposit(proposalID, depositorAddr, depositAmount)
|
||||
default:
|
||||
@ -233,7 +141,6 @@ func (keeper Keeper) AddDeposit(ctx context.Context, proposalID uint64, deposito
|
||||
// send to a destAddress if defined or burn otherwise.
|
||||
// Remaining funds are send back to the depositor.
|
||||
func (keeper Keeper) ChargeDeposit(ctx context.Context, proposalID uint64, destAddress, proposalCancelRate string) error {
|
||||
store := keeper.storeService.OpenKVStore(ctx)
|
||||
rate := sdkmath.LegacyMustNewDecFromStr(proposalCancelRate)
|
||||
var cancellationCharges sdk.Coins
|
||||
|
||||
@ -275,8 +182,7 @@ func (keeper Keeper) ChargeDeposit(ctx context.Context, proposalID uint64, destA
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = store.Delete(types.DepositKey(deposit.ProposalId, depositerAddress))
|
||||
err = keeper.Deposits.Remove(ctx, collections.Join(deposit.ProposalId, sdk.AccAddress(depositerAddress)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -317,27 +223,15 @@ func (keeper Keeper) ChargeDeposit(ctx context.Context, proposalID uint64, destA
|
||||
|
||||
// RefundAndDeleteDeposits refunds and deletes all the deposits on a specific proposal.
|
||||
func (keeper Keeper) RefundAndDeleteDeposits(ctx context.Context, proposalID uint64) error {
|
||||
store := keeper.storeService.OpenKVStore(ctx)
|
||||
|
||||
err := keeper.IterateDeposits(ctx, proposalID, func(deposit v1.Deposit) error {
|
||||
depositor, err := keeper.authKeeper.StringToBytes(deposit.Depositor)
|
||||
return keeper.IterateDeposits(ctx, proposalID, func(key collections.Pair[uint64, sdk.AccAddress], deposit v1.Deposit) (bool, error) {
|
||||
depositor := key.K2()
|
||||
err := keeper.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, depositor, deposit.Amount)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
|
||||
err = keeper.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, depositor, deposit.Amount)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = store.Delete(types.DepositKey(proposalID, depositor))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
err = keeper.Deposits.Remove(ctx, key)
|
||||
return false, err
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// validateInitialDeposit validates if initial deposit is greater than or equal to the minimum
|
||||
|
||||
@ -4,6 +4,8 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@ -12,7 +14,6 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
)
|
||||
|
||||
@ -68,8 +69,8 @@ func TestDeposits(t *testing.T) {
|
||||
require.True(t, sdk.NewCoins(proposal.TotalDeposit...).Equal(sdk.NewCoins()))
|
||||
|
||||
// Check no deposits at beginning
|
||||
_, err = govKeeper.GetDeposit(ctx, proposalID, TestAddrs[1])
|
||||
require.ErrorIs(t, err, types.ErrDepositNotFound)
|
||||
_, err = govKeeper.Deposits.Get(ctx, collections.Join(proposalID, TestAddrs[1]))
|
||||
require.ErrorIs(t, err, collections.ErrNotFound)
|
||||
proposal, err = govKeeper.GetProposal(ctx, proposalID)
|
||||
require.Nil(t, err)
|
||||
require.Nil(t, proposal.VotingStartTime)
|
||||
@ -78,7 +79,7 @@ func TestDeposits(t *testing.T) {
|
||||
votingStarted, err := govKeeper.AddDeposit(ctx, proposalID, TestAddrs[0], fourStake)
|
||||
require.NoError(t, err)
|
||||
require.False(t, votingStarted)
|
||||
deposit, err := govKeeper.GetDeposit(ctx, proposalID, TestAddrs[0])
|
||||
deposit, err := govKeeper.Deposits.Get(ctx, collections.Join(proposalID, TestAddrs[0]))
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, fourStake, sdk.NewCoins(deposit.Amount...))
|
||||
require.Equal(t, TestAddrs[0].String(), deposit.Depositor)
|
||||
@ -91,7 +92,7 @@ func TestDeposits(t *testing.T) {
|
||||
votingStarted, err = govKeeper.AddDeposit(ctx, proposalID, TestAddrs[0], fiveStake)
|
||||
require.NoError(t, err)
|
||||
require.False(t, votingStarted)
|
||||
deposit, err = govKeeper.GetDeposit(ctx, proposalID, TestAddrs[0])
|
||||
deposit, err = govKeeper.Deposits.Get(ctx, collections.Join(proposalID, TestAddrs[0]))
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, fourStake.Add(fiveStake...), sdk.NewCoins(deposit.Amount...))
|
||||
require.Equal(t, TestAddrs[0].String(), deposit.Depositor)
|
||||
@ -104,7 +105,7 @@ func TestDeposits(t *testing.T) {
|
||||
votingStarted, err = govKeeper.AddDeposit(ctx, proposalID, TestAddrs[1], fourStake)
|
||||
require.NoError(t, err)
|
||||
require.True(t, votingStarted)
|
||||
deposit, err = govKeeper.GetDeposit(ctx, proposalID, TestAddrs[1])
|
||||
deposit, err = govKeeper.Deposits.Get(ctx, collections.Join(proposalID, TestAddrs[1]))
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, TestAddrs[1].String(), deposit.Depositor)
|
||||
require.Equal(t, fourStake, sdk.NewCoins(deposit.Amount...))
|
||||
@ -120,7 +121,12 @@ func TestDeposits(t *testing.T) {
|
||||
|
||||
// Test deposit iterator
|
||||
// NOTE order of deposits is determined by the addresses
|
||||
deposits, _ := govKeeper.GetAllDeposits(ctx)
|
||||
var deposits v1.Deposits
|
||||
err = govKeeper.Deposits.Walk(ctx, nil, func(_ collections.Pair[uint64, sdk.AccAddress], deposit v1.Deposit) (bool, error) {
|
||||
deposits = append(deposits, &deposit)
|
||||
return false, nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, deposits, 2)
|
||||
propDeposits, _ := govKeeper.GetDeposits(ctx, proposalID)
|
||||
require.Equal(t, deposits, propDeposits)
|
||||
@ -130,12 +136,12 @@ func TestDeposits(t *testing.T) {
|
||||
require.Equal(t, fourStake, sdk.NewCoins(deposits[1].Amount...))
|
||||
|
||||
// Test Refund Deposits
|
||||
deposit, err = govKeeper.GetDeposit(ctx, proposalID, TestAddrs[1])
|
||||
deposit, err = govKeeper.Deposits.Get(ctx, collections.Join(proposalID, TestAddrs[1]))
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, fourStake, sdk.NewCoins(deposit.Amount...))
|
||||
govKeeper.RefundAndDeleteDeposits(ctx, proposalID)
|
||||
deposit, err = govKeeper.GetDeposit(ctx, proposalID, TestAddrs[1])
|
||||
require.ErrorIs(t, err, types.ErrDepositNotFound)
|
||||
deposit, err = govKeeper.Deposits.Get(ctx, collections.Join(proposalID, TestAddrs[1]))
|
||||
require.ErrorIs(t, err, collections.ErrNotFound)
|
||||
require.Equal(t, addr0Initial, bankKeeper.GetAllBalances(ctx, TestAddrs[0]))
|
||||
require.Equal(t, addr1Initial, bankKeeper.GetAllBalances(ctx, TestAddrs[1]))
|
||||
|
||||
|
||||
@ -3,6 +3,8 @@ package keeper
|
||||
import (
|
||||
"context"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
@ -91,9 +93,9 @@ func (q queryServer) Proposals(ctx context.Context, req *v1.QueryProposalsReques
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = q.k.GetDeposit(ctx, p.Id, depositor)
|
||||
has, err := q.k.Deposits.Has(ctx, collections.Join(p.Id, sdk.AccAddress(depositor)))
|
||||
// if no error, deposit found, matchDepositor = true
|
||||
matchDepositor = err == nil
|
||||
matchDepositor = err == nil && has
|
||||
}
|
||||
|
||||
if matchVoter && matchDepositor && matchStatus {
|
||||
@ -225,13 +227,9 @@ func (q queryServer) Deposit(ctx context.Context, req *v1.QueryDepositRequest) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deposit, err := q.k.GetDeposit(ctx, req.ProposalId, depositor)
|
||||
deposit, err := q.k.Deposits.Get(ctx, collections.Join(req.ProposalId, sdk.AccAddress(depositor)))
|
||||
if err != nil {
|
||||
if errors.IsOf(err, types.ErrDepositNotFound) {
|
||||
return nil, status.Errorf(codes.InvalidArgument,
|
||||
"depositer: %v not found for proposal: %v", req.Depositor, req.ProposalId)
|
||||
}
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
return nil, status.Error(codes.NotFound, err.Error())
|
||||
}
|
||||
|
||||
return &v1.QueryDepositResponse{Deposit: &deposit}, nil
|
||||
@ -248,19 +246,10 @@ func (q queryServer) Deposits(ctx context.Context, req *v1.QueryDepositsRequest)
|
||||
}
|
||||
|
||||
var deposits []*v1.Deposit
|
||||
|
||||
store := q.k.storeService.OpenKVStore(ctx)
|
||||
depositStore := prefix.NewStore(runtime.KVStoreAdapter(store), types.DepositsKey(req.ProposalId))
|
||||
|
||||
pageRes, err := query.Paginate(depositStore, req.Pagination, func(key, value []byte) error {
|
||||
var deposit v1.Deposit
|
||||
if err := q.k.cdc.Unmarshal(value, &deposit); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, pageRes, err := query.CollectionFilteredPaginate(ctx, q.k.Deposits, req.Pagination, func(_ collections.Pair[uint64, sdk.AccAddress], deposit v1.Deposit) (bool, error) {
|
||||
deposits = append(deposits, &deposit)
|
||||
return nil
|
||||
})
|
||||
return false, nil // we don't include results as they're being appended to the slice above.
|
||||
}, query.WithCollectionPaginationPairPrefix[uint64, sdk.AccAddress](req.ProposalId))
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
@ -13,23 +16,19 @@ func RegisterInvariants(ir sdk.InvariantRegistry, keeper *Keeper, bk types.BankK
|
||||
ir.RegisterRoute(types.ModuleName, "module-account", ModuleAccountInvariant(keeper, bk))
|
||||
}
|
||||
|
||||
// AllInvariants runs all invariants of the governance module
|
||||
func AllInvariants(keeper *Keeper, bk types.BankKeeper) sdk.Invariant {
|
||||
return func(ctx sdk.Context) (string, bool) {
|
||||
return ModuleAccountInvariant(keeper, bk)(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// ModuleAccountInvariant checks that the module account coins reflects the sum of
|
||||
// deposit amounts held on store.
|
||||
func ModuleAccountInvariant(keeper *Keeper, bk types.BankKeeper) sdk.Invariant {
|
||||
return func(ctx sdk.Context) (string, bool) {
|
||||
var expectedDeposits sdk.Coins
|
||||
|
||||
keeper.IterateAllDeposits(ctx, func(deposit v1.Deposit) error {
|
||||
expectedDeposits = expectedDeposits.Add(deposit.Amount...)
|
||||
return nil
|
||||
err := keeper.Deposits.Walk(ctx, nil, func(key collections.Pair[uint64, sdk.AccAddress], value v1.Deposit) (stop bool, err error) {
|
||||
expectedDeposits = expectedDeposits.Add(value.Amount...)
|
||||
return false, nil
|
||||
})
|
||||
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
macc := keeper.GetGovernanceAccount(ctx)
|
||||
balances := bk.GetAllBalances(ctx, macc.GetAddress())
|
||||
|
||||
@ -53,6 +53,7 @@ type Keeper struct {
|
||||
Schema collections.Schema
|
||||
Constitution collections.Item[string]
|
||||
Params collections.Item[v1.Params]
|
||||
Deposits collections.Map[collections.Pair[uint64, sdk.AccAddress], v1.Deposit]
|
||||
}
|
||||
|
||||
// GetAuthority returns the x/gov module's authority.
|
||||
@ -99,6 +100,7 @@ func NewKeeper(
|
||||
authority: authority,
|
||||
Constitution: collections.NewItem(sb, types.ConstitutionKey, "constitution", collections.StringValue),
|
||||
Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[v1.Params](cdc)),
|
||||
Deposits: collections.NewMap(sb, types.DepositsKeyPrefix, "deposits", collections.PairKeyCodec(collections.Uint64Key, sdk.AddressKeyAsIndexKey(sdk.AccAddressKey)), codec.CollValue[v1.Deposit](cdc)), //nolint: staticcheck // Needed to retain state compatibility
|
||||
}
|
||||
schema, err := sb.Build()
|
||||
if err != nil {
|
||||
|
||||
@ -6,6 +6,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
@ -323,7 +325,7 @@ func (keeper Keeper) GetProposalsFiltered(ctx context.Context, params v1.QueryPr
|
||||
|
||||
// match depositor (if supplied)
|
||||
if len(params.Depositor) > 0 {
|
||||
_, err = keeper.GetDeposit(ctx, p.Id, params.Depositor)
|
||||
_, err = keeper.Deposits.Get(ctx, collections.Join(p.Id, params.Depositor))
|
||||
// if no error, deposit found, matchDepositor = true
|
||||
matchDepositor = err == nil
|
||||
}
|
||||
|
||||
@ -5,6 +5,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/address"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@ -64,7 +67,7 @@ func TestMigrateStore(t *testing.T) {
|
||||
{
|
||||
"DepositKey",
|
||||
v1.DepositKey(proposalID, addr1), dummyValue,
|
||||
types.DepositKey(proposalID, addr1), dummyValue,
|
||||
depositKey(proposalID, addr1), dummyValue,
|
||||
},
|
||||
{
|
||||
"VotesKeyPrefix",
|
||||
@ -94,3 +97,9 @@ func TestMigrateStore(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// depositKey key of a specific deposit from the store.
|
||||
// NOTE(tip): legacy, eventually remove me.
|
||||
func depositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte {
|
||||
return append(append(types.DepositsKeyPrefix, sdk.Uint64ToBigEndian(proposalID)...), address.MustLengthPrefix(depositorAddr.Bytes())...)
|
||||
}
|
||||
|
||||
@ -353,7 +353,7 @@ func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.Weight
|
||||
|
||||
// RegisterStoreDecoder registers a decoder for gov module's types
|
||||
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
|
||||
sdr[govtypes.StoreKey] = simulation.NewDecodeStore(am.cdc)
|
||||
sdr[govtypes.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema)
|
||||
}
|
||||
|
||||
// WeightedOperations returns the all the gov module operations with their respective weights.
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
package simulation
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/types/kv"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's
|
||||
// Value to the corresponding gov type.
|
||||
func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string {
|
||||
return func(kvA, kvB kv.Pair) string {
|
||||
switch {
|
||||
case bytes.Equal(kvA.Key[:1], types.ProposalsKeyPrefix):
|
||||
var (
|
||||
proposalA v1beta1.Proposal
|
||||
proposalB v1beta1.Proposal
|
||||
|
||||
proposalD v1.Proposal
|
||||
proposalC v1.Proposal
|
||||
)
|
||||
if err := cdc.Unmarshal(kvA.Value, &proposalC); err != nil {
|
||||
cdc.MustUnmarshal(kvA.Value, &proposalA)
|
||||
}
|
||||
|
||||
if err := cdc.Unmarshal(kvB.Value, &proposalD); err != nil {
|
||||
cdc.MustUnmarshal(kvB.Value, &proposalB)
|
||||
}
|
||||
|
||||
// this is to check if the proposal has been unmarshalled as v1 correctly (and not v1beta1)
|
||||
if proposalC.Title != "" || proposalD.Title != "" {
|
||||
return fmt.Sprintf("%v\n%v", proposalC, proposalD)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v\n%v", proposalA, proposalB)
|
||||
case bytes.Equal(kvA.Key[:1], types.ActiveProposalQueuePrefix),
|
||||
bytes.Equal(kvA.Key[:1], types.InactiveProposalQueuePrefix),
|
||||
bytes.Equal(kvA.Key[:1], types.ProposalIDKey):
|
||||
proposalIDA := binary.LittleEndian.Uint64(kvA.Value)
|
||||
proposalIDB := binary.LittleEndian.Uint64(kvB.Value)
|
||||
return fmt.Sprintf("proposalIDA: %d\nProposalIDB: %d", proposalIDA, proposalIDB)
|
||||
|
||||
case bytes.Equal(kvA.Key[:1], types.DepositsKeyPrefix):
|
||||
var depositA, depositB v1beta1.Deposit
|
||||
cdc.MustUnmarshal(kvA.Value, &depositA)
|
||||
cdc.MustUnmarshal(kvB.Value, &depositB)
|
||||
return fmt.Sprintf("%v\n%v", depositA, depositB)
|
||||
|
||||
case bytes.Equal(kvA.Key[:1], types.VotesKeyPrefix):
|
||||
var voteA, voteB v1beta1.Vote
|
||||
cdc.MustUnmarshal(kvA.Value, &voteA)
|
||||
cdc.MustUnmarshal(kvB.Value, &voteB)
|
||||
return fmt.Sprintf("%v\n%v", voteA, voteB)
|
||||
|
||||
case bytes.Equal(kvA.Key[:1], types.VotingPeriodProposalKeyPrefix):
|
||||
return fmt.Sprintf("%v\n%v", kvA.Value, kvB.Value)
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("invalid governance key prefix %X", kvA.Key[:1]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,103 +0,0 @@
|
||||
package simulation_test
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/kv"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
var (
|
||||
delPk1 = ed25519.GenPrivKey().PubKey()
|
||||
delAddr1 = sdk.AccAddress(delPk1.Address())
|
||||
)
|
||||
|
||||
func TestDecodeStore(t *testing.T) {
|
||||
cdc := moduletestutil.MakeTestEncodingConfig(gov.AppModuleBasic{}).Codec
|
||||
dec := simulation.NewDecodeStore(cdc)
|
||||
|
||||
endTime := time.Now().UTC()
|
||||
content, ok := v1beta1.ContentFromProposalType("test", "test", v1beta1.ProposalTypeText)
|
||||
require.True(t, ok)
|
||||
proposalA, err := v1beta1.NewProposal(content, 1, endTime, endTime.Add(24*time.Hour))
|
||||
require.NoError(t, err)
|
||||
proposalB, err := v1beta1.NewProposal(content, 2, endTime, endTime.Add(24*time.Hour))
|
||||
require.NoError(t, err)
|
||||
proposalC, err := v1.NewProposal([]sdk.Msg{}, 3, endTime, endTime.Add(24*time.Hour), "metadata", "title", "summary", delAddr1, false)
|
||||
require.NoError(t, err)
|
||||
proposalD, err := v1.NewProposal([]sdk.Msg{}, 4, endTime, endTime.Add(24*time.Hour), "metadata", "title", "summary", delAddr1, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
proposalIDBz := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(proposalIDBz, 1)
|
||||
deposit := v1beta1.NewDeposit(1, delAddr1, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.OneInt())))
|
||||
vote := v1beta1.NewVote(1, delAddr1, v1beta1.NewNonSplitVoteOption(v1beta1.OptionYes))
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
kvA, kvB kv.Pair
|
||||
expectedLog string
|
||||
wantPanic bool
|
||||
}{
|
||||
{
|
||||
"proposals v1beta",
|
||||
kv.Pair{Key: types.ProposalKey(1), Value: cdc.MustMarshal(&proposalA)},
|
||||
kv.Pair{Key: types.ProposalKey(2), Value: cdc.MustMarshal(&proposalB)},
|
||||
fmt.Sprintf("%v\n%v", proposalA, proposalB), false,
|
||||
},
|
||||
{
|
||||
"proposals v1",
|
||||
kv.Pair{Key: types.ProposalKey(3), Value: cdc.MustMarshal(&proposalC)},
|
||||
kv.Pair{Key: types.ProposalKey(4), Value: cdc.MustMarshal(&proposalD)},
|
||||
fmt.Sprintf("%v\n%v", proposalC, proposalD), false,
|
||||
},
|
||||
{
|
||||
"proposal IDs",
|
||||
kv.Pair{Key: types.InactiveProposalQueueKey(1, endTime), Value: proposalIDBz},
|
||||
kv.Pair{Key: types.InactiveProposalQueueKey(1, endTime), Value: proposalIDBz},
|
||||
"proposalIDA: 1\nProposalIDB: 1", false,
|
||||
},
|
||||
{
|
||||
"deposits",
|
||||
kv.Pair{Key: types.DepositKey(1, delAddr1), Value: cdc.MustMarshal(&deposit)},
|
||||
kv.Pair{Key: types.DepositKey(1, delAddr1), Value: cdc.MustMarshal(&deposit)},
|
||||
fmt.Sprintf("%v\n%v", deposit, deposit), false,
|
||||
},
|
||||
{
|
||||
"votes",
|
||||
kv.Pair{Key: types.VoteKey(1, delAddr1), Value: cdc.MustMarshal(&vote)},
|
||||
kv.Pair{Key: types.VoteKey(1, delAddr1), Value: cdc.MustMarshal(&vote)},
|
||||
fmt.Sprintf("%v\n%v", vote, vote), false,
|
||||
},
|
||||
{
|
||||
"other",
|
||||
kv.Pair{Key: []byte{0x99}, Value: []byte{0x99}},
|
||||
kv.Pair{Key: []byte{0x99}, Value: []byte{0x99}},
|
||||
"", true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.wantPanic {
|
||||
require.Panics(t, func() { dec(tt.kvA, tt.kvB) }, tt.name)
|
||||
} else {
|
||||
require.Equal(t, tt.expectedLog, dec(tt.kvA, tt.kvB), tt.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -27,6 +27,7 @@ import (
|
||||
_ "github.com/cosmos/cosmos-sdk/x/consensus"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
dk "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/gov"
|
||||
govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/simulation"
|
||||
|
||||
@ -19,14 +19,11 @@ var (
|
||||
ErrNoProposalMsgs = errors.Register(ModuleName, 11, "no messages proposed")
|
||||
ErrInvalidProposalMsg = errors.Register(ModuleName, 12, "invalid proposal message")
|
||||
ErrInvalidSigner = errors.Register(ModuleName, 13, "expected gov account as only signer for proposal message")
|
||||
ErrInvalidSignalMsg = errors.Register(ModuleName, 14, "signal message is invalid")
|
||||
ErrMetadataTooLong = errors.Register(ModuleName, 15, "metadata too long")
|
||||
ErrMinDepositTooSmall = errors.Register(ModuleName, 16, "minimum deposit is too small")
|
||||
ErrProposalNotFound = errors.Register(ModuleName, 17, "proposal is not found")
|
||||
ErrInvalidProposer = errors.Register(ModuleName, 18, "invalid proposer")
|
||||
ErrNoDeposits = errors.Register(ModuleName, 19, "no deposits found")
|
||||
ErrVotingPeriodEnded = errors.Register(ModuleName, 20, "voting period already ended")
|
||||
ErrInvalidProposal = errors.Register(ModuleName, 21, "invalid proposal")
|
||||
ErrDepositNotFound = errors.Register(ModuleName, 22, "deposit is not found")
|
||||
ErrVoteNotFound = errors.Register(ModuleName, 23, "vote is not found")
|
||||
)
|
||||
|
||||
@ -47,7 +47,7 @@ var (
|
||||
ProposalIDKey = []byte{0x03}
|
||||
VotingPeriodProposalKeyPrefix = []byte{0x04}
|
||||
|
||||
DepositsKeyPrefix = []byte{0x10}
|
||||
DepositsKeyPrefix = collections.NewPrefix(16)
|
||||
|
||||
VotesKeyPrefix = []byte{0x20}
|
||||
|
||||
@ -102,16 +102,6 @@ func InactiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte {
|
||||
return append(InactiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...)
|
||||
}
|
||||
|
||||
// DepositsKey gets the first part of the deposits key based on the proposalID
|
||||
func DepositsKey(proposalID uint64) []byte {
|
||||
return append(DepositsKeyPrefix, GetProposalIDBytes(proposalID)...)
|
||||
}
|
||||
|
||||
// DepositKey key of a specific deposit from the store
|
||||
func DepositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte {
|
||||
return append(DepositsKey(proposalID), address.MustLengthPrefix(depositorAddr.Bytes())...)
|
||||
}
|
||||
|
||||
// VotesKey gets the first part of the votes key based on the proposalID
|
||||
func VotesKey(proposalID uint64) []byte {
|
||||
return append(VotesKeyPrefix, GetProposalIDBytes(proposalID)...)
|
||||
|
||||
@ -36,17 +36,6 @@ func TestProposalKeys(t *testing.T) {
|
||||
require.Panics(t, func() { SplitInactiveProposalQueueKey([]byte("test")) })
|
||||
}
|
||||
|
||||
func TestDepositKeys(t *testing.T) {
|
||||
key := DepositsKey(2)
|
||||
proposalID := SplitProposalKey(key)
|
||||
require.Equal(t, int(proposalID), 2)
|
||||
|
||||
key = DepositKey(2, addr)
|
||||
proposalID, depositorAddr := SplitKeyDeposit(key)
|
||||
require.Equal(t, int(proposalID), 2)
|
||||
require.Equal(t, addr, depositorAddr)
|
||||
}
|
||||
|
||||
func TestVoteKeys(t *testing.T) {
|
||||
key := VotesKey(2)
|
||||
proposalID := SplitProposalKey(key)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user