Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(gov)!: use collections for deposit state management #16127

Merged
merged 42 commits into from
May 15, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
dddd529
move constitution to collections
May 11, 2023
3d8306b
move params to collections
May 11, 2023
e559d41
chore: CHANGELOG.md
May 11, 2023
41d8e73
address PR reviews
May 11, 2023
6bb70e6
be consistent
May 12, 2023
c503920
more test fixes
May 12, 2023
9bf4d8c
Merge branch 'main' into tip/gov/coll-params-constitution
testinginprod May 12, 2023
0cd34ed
use assert and not require
May 12, 2023
8fc50d7
Merge remote-tracking branch 'origin/tip/gov/coll-params-constitution…
May 12, 2023
915618b
fix prefixes numbers
May 12, 2023
d291e99
move deposit to collections1
May 12, 2023
6932323
move another part of deposits to use collections
May 12, 2023
0792749
Merge branch 'main' into tip/gov/coll-deposit
May 12, 2023
a9cc7ba
add panic in genesis
May 12, 2023
f29f12e
remove unused func
May 12, 2023
4e53600
more cleanups + format
May 12, 2023
99066f3
remove improt
May 12, 2023
b23e38d
change the collections API to error on walking
May 13, 2023
6af4aa9
chore: CHANGELOG.md
May 13, 2023
5191de7
lint bank
May 13, 2023
4f9bea7
remove unused error
May 13, 2023
3ee570e
remove unused errors
May 13, 2023
64bf12f
fix some minor thing
May 13, 2023
39c3c4a
Merge branch 'main' into tip/gov/coll-deposit
testinginprod May 13, 2023
a4fe45c
more minor things
May 13, 2023
66b7866
remove another method yet again
May 13, 2023
730116e
fmt
May 13, 2023
3a04628
Merge branch 'main' into tip/gov/coll-deposit
testinginprod May 15, 2023
44906b0
chore: changelog
May 15, 2023
abbe962
Merge remote-tracking branch 'origin/tip/gov/coll-deposit' into tip/g…
May 15, 2023
a69ed21
supress lint
May 15, 2023
9aa0be4
fix lint maybe
May 15, 2023
21efcb5
fix lint 2
May 15, 2023
c295c8f
Merge branch 'main' into tip/gov/coll-deposit
testinginprod May 15, 2023
7f8b066
go mod tidy all
May 15, 2023
667c4e3
Merge remote-tracking branch 'origin/tip/gov/coll-deposit' into tip/g…
May 15, 2023
2830f8a
Merge branch 'main' into tip/gov/coll-deposit
testinginprod May 15, 2023
72dd01b
remove dependency on another error pkg
May 15, 2023
d400342
Merge remote-tracking branch 'origin/tip/gov/coll-deposit' into tip/g…
May 15, 2023
98195ea
tidy again
May 15, 2023
f5eb34c
try fix confix
May 15, 2023
b60262f
Merge branch 'main' into tip/gov/coll-deposit
testinginprod May 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion x/gov/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -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...)
}

Expand Down
134 changes: 31 additions & 103 deletions x/gov/keeper/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package keeper

import (
"context"
"cosmossdk.io/collections"
stderr "errors"
"fmt"

"cosmossdk.io/errors"
Expand All @@ -15,85 +17,38 @@ import (
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 {
deposits = append(deposits, &deposit)
return nil
return false
})

return
}

// 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) bool {
coinsToBurn = coinsToBurn.Add(deposit.Amount...)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a behavioural change, for which we compute the total amount of coins to burn and then we burn them all in a single batch

_ = keeper.Deposits.Remove(ctx, key) // can't error, otherwise the iterator wouldn't report it
return false
})
if err != nil {
return err
}

return err
return keeper.bankKeeper.BurnCoins(ctx, types.ModuleName, coinsToBurn)
}

// IterateAllDeposits iterates over all the stored deposits and performs a callback function.
Expand Down Expand Up @@ -123,28 +78,12 @@ func (keeper Keeper) IterateAllDeposits(ctx context.Context, cb func(deposit v1.
}

// 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 {
pair := collections.NewPrefixedPairRange[uint64, sdk.AccAddress](proposalID)
err := keeper.Deposits.Walk(ctx, pair, cb)
if err != nil && !stderr.Is(err, collections.ErrInvalidIterator) {
return err
}

return nil
}

Expand Down Expand Up @@ -196,12 +135,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:
Expand Down Expand Up @@ -233,7 +172,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

Expand Down Expand Up @@ -275,11 +213,7 @@ func (keeper Keeper) ChargeDeposit(ctx context.Context, proposalID uint64, destA
return err
}
}

err = store.Delete(types.DepositKey(deposit.ProposalId, depositerAddress))
if err != nil {
return err
}
return keeper.Deposits.Remove(ctx, collections.Join(deposit.ProposalId, sdk.AccAddress(depositerAddress)))
}

// burn the cancellation fee or sent the cancellation charges to destination address.
Expand Down Expand Up @@ -317,25 +251,19 @@ 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)
if err != nil {
return err
}

var err error
iterErr := keeper.IterateDeposits(ctx, proposalID, func(key collections.Pair[uint64, sdk.AccAddress], deposit v1.Deposit) bool {
depositor := key.K2()
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 true
}
return nil
_ = keeper.Deposits.Remove(ctx, key) // cannot error
return false
})
if iterErr != nil {
return iterErr
}

return err
}
Expand Down
25 changes: 15 additions & 10 deletions x/gov/keeper/deposit_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper_test

import (
"cosmossdk.io/collections"
"fmt"
"testing"

Expand All @@ -12,7 +13,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"
)

Expand Down Expand Up @@ -68,8 +68,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)
Expand All @@ -78,7 +78,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)
Expand All @@ -91,7 +91,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)
Expand All @@ -104,7 +104,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...))
Expand All @@ -120,7 +120,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 {
deposits = append(deposits, &deposit)
return false
})
require.NoError(t, err)
require.Len(t, deposits, 2)
propDeposits, _ := govKeeper.GetDeposits(ctx, proposalID)
require.Equal(t, deposits, propDeposits)
Expand All @@ -130,12 +135,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]))

Expand Down
22 changes: 7 additions & 15 deletions x/gov/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"context"
"cosmossdk.io/collections"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand Down Expand Up @@ -91,9 +92,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)))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

behavioural change, perf improvement: uses Has instead of Get in order to avoid getting the value from store and decoding it

// if no error, deposit found, matchDepositor = true
matchDepositor = err == nil
matchDepositor = err == nil && has
}

if matchVoter && matchDepositor && matchStatus {
Expand Down Expand Up @@ -225,7 +226,7 @@ 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,
Expand All @@ -248,19 +249,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())
}
Expand Down
2 changes: 2 additions & 0 deletions x/gov/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)),
}
schema, err := sb.Build()
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion x/gov/keeper/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"context"
"cosmossdk.io/collections"
"errors"
"fmt"
"time"
Expand Down Expand Up @@ -323,7 +324,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
}
Expand Down
Loading