diff --git a/CHANGELOG.md b/CHANGELOG.md index 11ffada70624..eec5965038a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (types) [\#12201](https://github.com/cosmos/cosmos-sdk/pull/12201) Add `MustAccAddressFromBech32` util function * [\#11693](https://github.com/cosmos/cosmos-sdk/pull/11693) Add validation for gentx cmd. * [\#11686](https://github.com/cosmos/cosmos-sdk/pull/11686) Update the min required Golang version to `1.17`. * (x/auth/vesting) [\#11652](https://github.com/cosmos/cosmos-sdk/pull/11652) Add util functions for `Period(s)` diff --git a/simapp/export.go b/simapp/export.go index 05346741b99e..efa1796a462e 100644 --- a/simapp/export.go +++ b/simapp/export.go @@ -116,10 +116,7 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs [] panic(err) } - delAddr, err := app.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(delegation.DelegatorAddress) - if err != nil { - panic(err) - } + delAddr := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) _, _ = app.DistrKeeper.WithdrawDelegationRewards(ctx, delAddr, valAddr) } @@ -175,20 +172,9 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs [] if err != nil { panic(err) } - delAddr, err := app.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(del.DelegatorAddress) - if err != nil { - panic(err) - } - - if err := app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr); err != nil { - // never called as BeforeDelegationCreated always returns nil - panic(fmt.Errorf("error while incrementing period: %w", err)) - } - - if err := app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr); err != nil { - // never called as AfterDelegationModified always returns nil - panic(fmt.Errorf("error while creating a new delegation period record: %w", err)) - } + delAddr := sdk.MustAccAddressFromBech32(del.DelegatorAddress) + app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr) + app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr) } // reset context height diff --git a/types/address.go b/types/address.go index afe35755487b..5702d95fafa0 100644 --- a/types/address.go +++ b/types/address.go @@ -190,6 +190,16 @@ func MustAccAddressFromBech32(address string) AccAddress { return addr } +// MustAccAddressFromBech32 calls AccAddressFromBech32 and panics on error. +func MustAccAddressFromBech32(address string) AccAddress { + addr, err := AccAddressFromBech32(address) + if err != nil { + panic(err) + } + + return addr +} + // AccAddressFromBech32 creates an AccAddress from a Bech32 string. // Deprecated: Use an address.Codec to convert addresses from and to string/bytes. func AccAddressFromBech32(address string) (addr AccAddress, err error) { diff --git a/types/tx/types.go b/types/tx/types.go index ac2f01e404ca..723d67944bbc 100644 --- a/types/tx/types.go +++ b/types/tx/types.go @@ -121,17 +121,10 @@ func (t *Tx) GetSigners(cdc codec.Codec) ([][]byte, []protoreflect.Message, erro // ensure any specified fee payer is included in the required signers (at the end) feePayer := t.AuthInfo.Fee.Payer - var feePayerAddr []byte - if feePayer != "" { - var err error - feePayerAddr, err = cdc.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(feePayer) - if err != nil { - return nil, nil, err - } - } - if feePayerAddr != nil && !seen[string(feePayerAddr)] { - signers = append(signers, feePayerAddr) - seen[string(feePayerAddr)] = true + if feePayer != "" && !seen[feePayer] { + payerAddr := sdk.MustAccAddressFromBech32(feePayer) + signers = append(signers, payerAddr) + seen[feePayer] = true } return signers, reflectMsgs, nil @@ -148,11 +141,7 @@ func (t *Tx) GetFee() sdk.Coins { func (t *Tx) FeePayer(cdc codec.Codec) []byte { feePayer := t.AuthInfo.Fee.Payer if feePayer != "" { - feePayerAddr, err := cdc.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(feePayer) - if err != nil { - panic(err) - } - return feePayerAddr + return sdk.MustAccAddressFromBech32(feePayer) } // use first signer as default if no payer specified signers, _, err := t.GetSigners(cdc) @@ -163,15 +152,10 @@ func (t *Tx) FeePayer(cdc codec.Codec) []byte { return signers[0] } -func (t *Tx) FeeGranter(cdc codec.Codec) []byte { - feeGranter := t.AuthInfo.Fee.Granter - if feeGranter != "" { - feeGranterAddr, err := cdc.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(feeGranter) - if err != nil { - panic(err) - } - - return feeGranterAddr +func (t *Tx) FeeGranter() sdk.AccAddress { + feePayer := t.AuthInfo.Fee.Granter + if feePayer != "" { + return sdk.MustAccAddressFromBech32(feePayer) } return nil } diff --git a/x/auth/tx/builder.go b/x/auth/tx/builder.go index 423bca3a0870..7dbcebdadb93 100644 --- a/x/auth/tx/builder.go +++ b/x/auth/tx/builder.go @@ -109,29 +109,16 @@ var marshalOption = proto.MarshalOptions{ Deterministic: true, } -func (w *builder) getTx() (*gogoTxWrapper, error) { - anyMsgs, err := msgsV1toAnyV2(w.msgs) - if err != nil { - return nil, err - } - body := &txv1beta1.TxBody{ - Messages: anyMsgs, - Memo: w.memo, - TimeoutHeight: w.timeoutHeight, - TimeoutTimestamp: timestamppb.New(w.timeoutTimestamp), - Unordered: w.unordered, - ExtensionOptions: intoAnyV2(w.extensionOptions), - NonCriticalExtensionOptions: intoAnyV2(w.nonCriticalExtensionOptions), +func (w *wrapper) FeePayer() sdk.AccAddress { + feePayer := w.tx.AuthInfo.Fee.Payer + if feePayer != "" { + return sdk.MustAccAddressFromBech32(feePayer) } - fee, err := w.getFee() - if err != nil { - return nil, fmt.Errorf("unable to parse fee: %w", err) - } - authInfo := &txv1beta1.AuthInfo{ - SignerInfos: intoV2SignerInfo(w.signerInfos), - Fee: fee, - Tip: nil, // deprecated +func (w *wrapper) FeeGranter() sdk.AccAddress { + feePayer := w.tx.AuthInfo.Fee.Granter + if feePayer != "" { + return sdk.MustAccAddressFromBech32(feePayer) } bodyBytes, err := marshalOption.Marshal(body) diff --git a/x/authz/keeper/grpc_query.go b/x/authz/keeper/grpc_query.go index 3f74e2c1eb21..3eebab1bec17 100644 --- a/x/authz/keeper/grpc_query.go +++ b/x/authz/keeper/grpc_query.go @@ -106,7 +106,8 @@ func (k Keeper) GranterGrants(c context.Context, req *authz.QueryGranterGrantsRe var grants []*authz.GrantAuthorization pageRes, err := query.FilteredPaginate(authzStore, req.Pagination, func(key []byte, value []byte, - accumulate bool) (bool, error) { + accumulate bool, + ) (bool, error) { auth, err := unmarshalAuthorization(k.cdc, value) if err != nil { return false, err @@ -155,7 +156,8 @@ func (k Keeper) GranteeGrants(c context.Context, req *authz.QueryGranteeGrantsRe var authorizations []*authz.GrantAuthorization pageRes, err := query.FilteredPaginate(store, req.Pagination, func(key []byte, value []byte, - accumulate bool) (bool, error) { + accumulate bool, + ) (bool, error) { auth, err := unmarshalAuthorization(k.cdc, value) if err != nil { return false, err diff --git a/x/authz/keeper/keeper.go b/x/authz/keeper/keeper.go index ecfed97ee7cf..dd6104275d5c 100644 --- a/x/authz/keeper/keeper.go +++ b/x/authz/keeper/keeper.go @@ -83,10 +83,8 @@ func (k Keeper) updateGrant(ctx context.Context, grantee, granter sdk.AccAddress // DispatchActions attempts to execute the provided messages via authorization // grants from the message signer to the grantee. -func (k Keeper) DispatchActions(ctx context.Context, grantee sdk.AccAddress, msgs []sdk.Msg) ([][]byte, error) { +func (k Keeper) DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, msgs []sdk.Msg) ([][]byte, error) { results := make([][]byte, len(msgs)) - now := k.Environment.HeaderService.HeaderInfo(ctx).Time - for i, msg := range msgs { signers, _, err := k.cdc.GetMsgSigners(msg) if err != nil { @@ -348,12 +346,11 @@ func (k Keeper) GetAuthorization(ctx context.Context, grantee, granter sdk.AccAd // IterateGrants iterates over all authorization grants // This function should be used with caution because it can involve significant IO operations. // It should not be used in query or msg services without charging additional gas. -// The iteration stops when the handler function returns true or the iterator exhaust. -func (k Keeper) IterateGrants(ctx context.Context, - handler func(granterAddr, granteeAddr sdk.AccAddress, grant authz.Grant) (bool, error), -) error { - store := runtime.KVStoreAdapter(k.KVStoreService.OpenKVStore(ctx)) - iter := storetypes.KVStorePrefixIterator(store, GrantKey) +func (k Keeper) IterateGrants(ctx sdk.Context, + handler func(granterAddr sdk.AccAddress, granteeAddr sdk.AccAddress, grant authz.Grant) bool, +) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, GrantKey) defer iter.Close() for ; iter.Valid(); iter.Next() { var grant authz.Grant @@ -411,89 +408,17 @@ func (k Keeper) getGrantQueueItem(ctx context.Context, expiration time.Time, gra return &queueItems, nil } -func (k Keeper) setGrantQueueItem(ctx context.Context, expiration time.Time, - granter, grantee sdk.AccAddress, queueItems *authz.GrantQueueItem, -) error { - store := k.KVStoreService.OpenKVStore(ctx) - bz, err := k.cdc.Marshal(queueItems) - if err != nil { - return err - } - return store.Set(GrantQueueKey(expiration, granter, grantee), bz) -} - -// insertIntoGrantQueue inserts a grant key into the grant queue -func (k Keeper) insertIntoGrantQueue(ctx context.Context, granter, grantee sdk.AccAddress, msgType string, expiration time.Time) error { - queueItems, err := k.getGrantQueueItem(ctx, expiration, granter, grantee) - if err != nil { - return err - } - - queueItems.MsgTypeUrls = append(queueItems.MsgTypeUrls, msgType) - return k.setGrantQueueItem(ctx, expiration, granter, grantee, queueItems) -} - -// removeFromGrantQueue removes a grant key from the grant queue -func (k Keeper) removeFromGrantQueue(ctx context.Context, grantKey []byte, granter, grantee sdk.AccAddress, expiration time.Time) error { - store := k.KVStoreService.OpenKVStore(ctx) - key := GrantQueueKey(expiration, granter, grantee) - bz, err := store.Get(key) - if err != nil { - return err - } - - if bz == nil { - return errorsmod.Wrap(authz.ErrNoGrantKeyFound, "can't remove grant from the expire queue, grant key not found") - } - - var queueItem authz.GrantQueueItem - if err := k.cdc.Unmarshal(bz, &queueItem); err != nil { - return err - } - - _, _, msgType := parseGrantStoreKey(grantKey) - queueItems := queueItem.MsgTypeUrls - - for index, typeURL := range queueItems { - if err := k.GasService.GasMeter(ctx).Consume(gasCostPerIteration, "grant queue"); err != nil { - return err - } - - if typeURL == msgType { - end := len(queueItem.MsgTypeUrls) - 1 - queueItems[index] = queueItems[end] - queueItems = queueItems[:end] - - if err := k.setGrantQueueItem(ctx, expiration, granter, grantee, &authz.GrantQueueItem{ - MsgTypeUrls: queueItems, - }); err != nil { - return err - } - break - } - } - - return nil -} - -// DequeueAndDeleteExpiredGrants deletes expired grants from the state and grant queue. -func (k Keeper) DequeueAndDeleteExpiredGrants(ctx context.Context, limit int) error { - store := k.KVStoreService.OpenKVStore(ctx) - - iterator, err := store.Iterator(GrantQueuePrefix, storetypes.InclusiveEndBytes(GrantQueueTimePrefix(k.HeaderService.HeaderInfo(ctx).Time))) - if err != nil { - return err - } - defer iterator.Close() - - count := 0 - for ; iterator.Valid(); iterator.Next() { - var queueItem authz.GrantQueueItem - if err := k.cdc.Unmarshal(iterator.Value(), &queueItem); err != nil { - return err +// InitGenesis new authz genesis +func (k Keeper) InitGenesis(ctx sdk.Context, data *authz.GenesisState) { + for _, entry := range data.Authorization { + grantee := sdk.MustAccAddressFromBech32(entry.Grantee) + granter := sdk.MustAccAddressFromBech32(entry.Granter) + a, ok := entry.Authorization.GetCachedValue().(authz.Authorization) + if !ok { + panic("expected authorization") } - _, granter, grantee, err := parseGrantQueueKey(iterator.Key()) + err := k.SaveGrant(ctx, grantee, granter, a, entry.Expiration) if err != nil { return err } diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go index 8e422e5f420c..426547646521 100644 --- a/x/bank/keeper/genesis.go +++ b/x/bank/keeper/genesis.go @@ -30,10 +30,6 @@ func (k BaseKeeper) InitGenesis(ctx context.Context, genState *types.GenesisStat for _, balance := range genState.Balances { addr := balance.GetAddress() - bz, err := k.ak.AddressCodec().StringToBytes(addr) - if err != nil { - return err - } for _, coin := range balance.Coins { err := k.Balances.Set(ctx, collections.Join(sdk.AccAddress(bz), coin.Denom), coin.Amount) diff --git a/x/bank/keeper/msg_server.go b/x/bank/keeper/msg_server.go index 81d4d2321476..54ae2c031dd2 100644 --- a/x/bank/keeper/msg_server.go +++ b/x/bank/keeper/msg_server.go @@ -90,17 +90,10 @@ func (k msgServer) MultiSend(ctx context.Context, msg *types.MsgMultiSend) (*typ } for _, out := range msg.Outputs { - if base, ok := k.Keeper.(BaseKeeper); ok { - accAddr, err := base.ak.AddressCodec().StringToBytes(out.Address) - if err != nil { - return nil, err - } - - if k.BlockedAddr(accAddr) { - return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", out.Address) - } - } else { - return nil, sdkerrors.ErrInvalidRequest.Wrapf("invalid keeper type: %T", k.Keeper) + accAddr := sdk.MustAccAddressFromBech32(out.Address) + + if k.BlockedAddr(accAddr) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive transactions", out.Address) } } diff --git a/x/bank/types/balance.go b/x/bank/types/balance.go index 32c90d7c953f..a2c7eb55b021 100644 --- a/x/bank/types/balance.go +++ b/x/bank/types/balance.go @@ -3,7 +3,6 @@ package types import ( "bytes" "encoding/json" - "fmt" "sort" "cosmossdk.io/core/address" @@ -16,8 +15,8 @@ import ( var _ exported.GenesisBalance = (*Balance)(nil) // GetAddress returns the account address of the Balance object. -func (b Balance) GetAddress() string { - return b.Address +func (b Balance) GetAddress() sdk.AccAddress { + return sdk.MustAccAddressFromBech32(b.Address) } // GetCoins returns the account coins of the Balance object. diff --git a/x/distribution/keeper/genesis.go b/x/distribution/keeper/genesis.go index b6fa562268e4..d24649872c9d 100644 --- a/x/distribution/keeper/genesis.go +++ b/x/distribution/keeper/genesis.go @@ -23,15 +23,15 @@ func (k Keeper) InitGenesis(ctx context.Context, data types.GenesisState) error } for _, dwi := range data.DelegatorWithdrawInfos { - delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(dwi.DelegatorAddress) - if err != nil { - return err - } - withdrawAddress, err := k.authKeeper.AddressCodec().StringToBytes(dwi.WithdrawAddress) - if err != nil { - return err - } - err = k.DelegatorsWithdrawAddress.Set(ctx, delegatorAddress, withdrawAddress) + delegatorAddress := sdk.MustAccAddressFromBech32(dwi.DelegatorAddress) + withdrawAddress := sdk.MustAccAddressFromBech32(dwi.WithdrawAddress) + k.SetDelegatorWithdrawAddr(ctx, delegatorAddress, withdrawAddress) + } + + var previousProposer sdk.ConsAddress + if data.PreviousProposer != "" { + var err error + previousProposer, err = sdk.ConsAddressFromBech32(data.PreviousProposer) if err != nil { return err } @@ -83,15 +83,9 @@ func (k Keeper) InitGenesis(ctx context.Context, data types.GenesisState) error if err != nil { return err } - delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(del.DelegatorAddress) - if err != nil { - return err - } + delegatorAddress := sdk.MustAccAddressFromBech32(del.DelegatorAddress) - err = k.DelegatorStartingInfo.Set(ctx, collections.Join(sdk.ValAddress(valAddr), sdk.AccAddress(delegatorAddress)), del.StartingInfo) - if err != nil { - return err - } + k.SetDelegatorStartingInfo(ctx, valAddr, delegatorAddress, del.StartingInfo) } for _, evt := range data.ValidatorSlashEvents { valAddr, err := k.stakingKeeper.ValidatorAddressCodec().StringToBytes(evt.ValidatorAddress) diff --git a/x/gov/keeper/deposit.go b/x/gov/keeper/deposit.go index e3ac7138479c..afe7ca604300 100644 --- a/x/gov/keeper/deposit.go +++ b/x/gov/keeper/deposit.go @@ -18,12 +18,12 @@ import ( ) // SetDeposit sets a Deposit to the gov store -func (k Keeper) SetDeposit(ctx context.Context, deposit v1.Deposit) error { - depositor, err := k.authKeeper.AddressCodec().StringToBytes(deposit.Depositor) - if err != nil { - return err - } - return k.Deposits.Set(ctx, collections.Join(deposit.ProposalId, sdk.AccAddress(depositor)), deposit) +func (keeper Keeper) SetDeposit(ctx sdk.Context, deposit types.Deposit) { + store := ctx.KVStore(keeper.storeKey) + bz := keeper.cdc.MustMarshal(&deposit) + depositor := sdk.MustAccAddressFromBech32(deposit.Depositor) + + store.Set(types.DepositKey(deposit.ProposalId, depositor), bz) } // GetDeposits returns all the deposits of a proposal @@ -57,8 +57,11 @@ func (k Keeper) RefundAndDeleteDeposits(ctx context.Context, proposalID uint64) if err != nil { return false, err } - err = k.Deposits.Remove(ctx, key) - return false, err + + depositor := sdk.MustAccAddressFromBech32(deposit.Depositor) + + store.Delete(types.DepositKey(proposalID, depositor)) + return false }) } @@ -211,40 +214,10 @@ func (k Keeper) ChargeDeposit(ctx context.Context, proposalID uint64, destAddres return err } - for _, deposit := range deposits { - depositorAddress, err := k.authKeeper.AddressCodec().StringToBytes(deposit.Depositor) - if err != nil { - return err - } - - var remainingAmount sdk.Coins - - for _, coin := range deposit.Amount { - burnAmount := sdkmath.LegacyNewDecFromInt(coin.Amount).Mul(rate).TruncateInt() - // remaining amount = deposits amount - burn amount - remainingAmount = remainingAmount.Add( - sdk.NewCoin( - coin.Denom, - coin.Amount.Sub(burnAmount), - ), - ) - cancellationCharges = cancellationCharges.Add( - sdk.NewCoin( - coin.Denom, - burnAmount, - ), - ) - } + keeper.IterateDeposits(ctx, proposalID, func(deposit types.Deposit) bool { + depositor := sdk.MustAccAddressFromBech32(deposit.Depositor) - if !remainingAmount.IsZero() { - err := k.bankKeeper.SendCoinsFromModuleToAccount( - ctx, types.ModuleName, depositorAddress, remainingAmount, - ) - if err != nil { - return err - } - } - err = k.Deposits.Remove(ctx, collections.Join(deposit.ProposalId, sdk.AccAddress(depositorAddress))) + err := keeper.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, depositor, deposit.Amount) if err != nil { return err } diff --git a/x/gov/keeper/msg_server.go b/x/gov/keeper/msg_server.go index 8dca8c094fe1..bfe45be11e95 100644 --- a/x/gov/keeper/msg_server.go +++ b/x/gov/keeper/msg_server.go @@ -123,48 +123,14 @@ func (k msgServer) SubmitProposal(ctx context.Context, msg *v1.MsgSubmitProposal }, nil } -// SubmitMultipleChoiceProposal implements the MsgServer.SubmitMultipleChoiceProposal method. -func (k msgServer) SubmitMultipleChoiceProposal(ctx context.Context, msg *v1.MsgSubmitMultipleChoiceProposal) (*v1.MsgSubmitMultipleChoiceProposalResponse, error) { - resp, err := k.SubmitProposal(ctx, &v1.MsgSubmitProposal{ - InitialDeposit: msg.InitialDeposit, - Proposer: msg.Proposer, - Title: msg.Title, - Summary: msg.Summary, - Metadata: msg.Metadata, - ProposalType: v1.ProposalType_PROPOSAL_TYPE_MULTIPLE_CHOICE, - }) +func (k msgServer) Vote(goCtx context.Context, msg *types.MsgVote) (*types.MsgVoteResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + accAddr, err := sdk.AccAddressFromBech32(msg.Voter) if err != nil { return nil, err } - if msg.VoteOptions == nil { - return nil, sdkerrors.ErrInvalidRequest.Wrap("vote options cannot be nil") - } - - // check that if a vote option is provided, the previous one is also provided - if (msg.VoteOptions.OptionTwo != "" && msg.VoteOptions.OptionOne == "") || - (msg.VoteOptions.OptionThree != "" && msg.VoteOptions.OptionTwo == "") || - (msg.VoteOptions.OptionFour != "" && msg.VoteOptions.OptionThree == "") { - return nil, sdkerrors.ErrInvalidRequest.Wrap("if a vote option is provided, the previous one must also be provided") - } - - // check that at least two vote options are provided - if msg.VoteOptions.OptionOne == "" && msg.VoteOptions.OptionTwo == "" { - return nil, sdkerrors.ErrInvalidRequest.Wrap("vote options cannot be empty, two or more options must be provided") - } - - if err := k.ProposalVoteOptions.Set(ctx, resp.ProposalId, *msg.VoteOptions); err != nil { - return nil, err - } - - return &v1.MsgSubmitMultipleChoiceProposalResponse{ - ProposalId: resp.ProposalId, - }, nil -} - -// CancelProposal implements the MsgServer.CancelProposal method. -func (k msgServer) CancelProposal(ctx context.Context, msg *v1.MsgCancelProposal) (*v1.MsgCancelProposalResponse, error) { - _, err := k.authKeeper.AddressCodec().StringToBytes(msg.Proposer) + err = k.Keeper.AddVote(ctx, msg.ProposalId, accAddr, types.NewNonSplitVoteOption(msg.Option)) if err != nil { return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid proposer address: %s", err) } diff --git a/x/gov/keeper/tally.go b/x/gov/keeper/tally.go index 193895793caa..4d2f3628357f 100644 --- a/x/gov/keeper/tally.go +++ b/x/gov/keeper/tally.go @@ -248,15 +248,7 @@ func defaultCalculateVoteResultsAndVotingPower( votesToRemove := []collections.Pair[uint64, sdk.AccAddress]{} if err := k.Votes.Walk(ctx, rng, func(key collections.Pair[uint64, sdk.AccAddress], vote v1.Vote) (bool, error) { // if validator, just record it in the map - voter, err := k.authKeeper.AddressCodec().StringToBytes(vote.Voter) - if err != nil { - return false, err - } - - valAddrStr, err := k.sk.ValidatorAddressCodec().BytesToString(voter) - if err != nil { - return false, err - } + voter := sdk.MustAccAddressFromBech32(vote.Voter) if val, ok := validators[valAddrStr]; ok { val.Vote = vote.Options diff --git a/x/gov/keeper/vote.go b/x/gov/keeper/vote.go index 53156e6d8626..bf5ed9cd669d 100644 --- a/x/gov/keeper/vote.go +++ b/x/gov/keeper/vote.go @@ -35,10 +35,12 @@ func (k Keeper) AddVote(ctx context.Context, proposalID uint64, voterAddr sdk.Ac return err } - err = k.assertVoteOptionsLen(options) - if err != nil { - return err - } + store := ctx.KVStore(keeper.storeKey) + bz := keeper.cdc.MustMarshal(&vote) + addr := sdk.MustAccAddressFromBech32(vote.Voter) + + store.Set(types.VoteKey(vote.ProposalId, addr), bz) +} for _, option := range options { switch proposal.ProposalType { diff --git a/x/staking/genesis.go b/x/staking/genesis.go index d09ada842f44..581bbc7aa17c 100644 --- a/x/staking/genesis.go +++ b/x/staking/genesis.go @@ -13,15 +13,181 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// TODO: move this to sdk types and use this instead of comet types GenesisValidator -// then we can do pubkey conversion in ToGenesisDoc -// -// this is a temporary work around to avoid import comet directly in staking -type GenesisValidator struct { - Address sdk.ConsAddress - PubKey cryptotypes.PubKey - Power int64 - Name string +// InitGenesis sets the pool and parameters for the provided keeper. For each +// validator in data, it sets that validator in the keeper along with manually +// setting the indexes. In addition, it also sets any delegations found in +// data. Finally, it updates the bonded validators. +// Returns final validator set after applying all declaration and delegations +func InitGenesis( + ctx sdk.Context, keeper keeper.Keeper, accountKeeper types.AccountKeeper, + bankKeeper types.BankKeeper, data *types.GenesisState, +) (res []abci.ValidatorUpdate) { + bondedTokens := sdk.ZeroInt() + notBondedTokens := sdk.ZeroInt() + + // We need to pretend to be "n blocks before genesis", where "n" is the + // validator update delay, so that e.g. slashing periods are correctly + // initialized for the validator set e.g. with a one-block offset - the + // first TM block is at height 1, so state updates applied from + // genesis.json are in block 0. + ctx = ctx.WithBlockHeight(1 - sdk.ValidatorUpdateDelay) + + keeper.SetParams(ctx, data.Params) + keeper.SetLastTotalPower(ctx, data.LastTotalPower) + + for _, validator := range data.Validators { + keeper.SetValidator(ctx, validator) + + // Manually set indices for the first time + keeper.SetValidatorByConsAddr(ctx, validator) + keeper.SetValidatorByPowerIndex(ctx, validator) + + // Call the creation hook if not exported + if !data.Exported { + keeper.AfterValidatorCreated(ctx, validator.GetOperator()) + } + + // update timeslice if necessary + if validator.IsUnbonding() { + keeper.InsertUnbondingValidatorQueue(ctx, validator) + } + + switch validator.GetStatus() { + case types.Bonded: + bondedTokens = bondedTokens.Add(validator.GetTokens()) + case types.Unbonding, types.Unbonded: + notBondedTokens = notBondedTokens.Add(validator.GetTokens()) + default: + panic("invalid validator status") + } + } + + for _, delegation := range data.Delegations { + delegatorAddress := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) + + // Call the before-creation hook if not exported + if !data.Exported { + keeper.BeforeDelegationCreated(ctx, delegatorAddress, delegation.GetValidatorAddr()) + } + + keeper.SetDelegation(ctx, delegation) + // Call the after-modification hook if not exported + if !data.Exported { + keeper.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()) + } + } + + for _, ubd := range data.UnbondingDelegations { + keeper.SetUnbondingDelegation(ctx, ubd) + + for _, entry := range ubd.Entries { + keeper.InsertUBDQueue(ctx, ubd, entry.CompletionTime) + notBondedTokens = notBondedTokens.Add(entry.Balance) + } + } + + for _, red := range data.Redelegations { + keeper.SetRedelegation(ctx, red) + + for _, entry := range red.Entries { + keeper.InsertRedelegationQueue(ctx, red, entry.CompletionTime) + } + } + + bondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, bondedTokens)) + notBondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, notBondedTokens)) + + // check if the unbonded and bonded pools accounts exists + bondedPool := keeper.GetBondedPool(ctx) + if bondedPool == nil { + panic(fmt.Sprintf("%s module account has not been set", types.BondedPoolName)) + } + // TODO remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862 + bondedBalance := bankKeeper.GetAllBalances(ctx, bondedPool.GetAddress()) + if bondedBalance.IsZero() { + accountKeeper.SetModuleAccount(ctx, bondedPool) + } + // if balance is different from bonded coins panic because genesis is most likely malformed + if !bondedBalance.IsEqual(bondedCoins) { + panic(fmt.Sprintf("bonded pool balance is different from bonded coins: %s <-> %s", bondedBalance, bondedCoins)) + } + notBondedPool := keeper.GetNotBondedPool(ctx) + if notBondedPool == nil { + panic(fmt.Sprintf("%s module account has not been set", types.NotBondedPoolName)) + } + + notBondedBalance := bankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) + if notBondedBalance.IsZero() { + accountKeeper.SetModuleAccount(ctx, notBondedPool) + } + // if balance is different from non bonded coins panic because genesis is most likely malformed + if !notBondedBalance.IsEqual(notBondedCoins) { + panic(fmt.Sprintf("not bonded pool balance is different from not bonded coins: %s <-> %s", notBondedBalance, notBondedCoins)) + } + // don't need to run Tendermint updates if we exported + if data.Exported { + for _, lv := range data.LastValidatorPowers { + valAddr, err := sdk.ValAddressFromBech32(lv.Address) + if err != nil { + panic(err) + } + keeper.SetLastValidatorPower(ctx, valAddr, lv.Power) + validator, found := keeper.GetValidator(ctx, valAddr) + + if !found { + panic(fmt.Sprintf("validator %s not found", lv.Address)) + } + + update := validator.ABCIValidatorUpdate(keeper.PowerReduction(ctx)) + update.Power = lv.Power // keep the next-val-set offset, use the last power for the first block + res = append(res, update) + } + } else { + var err error + res, err = keeper.ApplyAndReturnValidatorSetUpdates(ctx) + if err != nil { + log.Fatal(err) + } + } + + return res +} + +// ExportGenesis returns a GenesisState for a given context and keeper. The +// GenesisState will contain the pool, params, validators, and bonds found in +// the keeper. +func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { + var unbondingDelegations []types.UnbondingDelegation + + keeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) { + unbondingDelegations = append(unbondingDelegations, ubd) + return false + }) + + var redelegations []types.Redelegation + + keeper.IterateRedelegations(ctx, func(_ int64, red types.Redelegation) (stop bool) { + redelegations = append(redelegations, red) + return false + }) + + var lastValidatorPowers []types.LastValidatorPower + + keeper.IterateLastValidatorPowers(ctx, func(addr sdk.ValAddress, power int64) (stop bool) { + lastValidatorPowers = append(lastValidatorPowers, types.LastValidatorPower{Address: addr.String(), Power: power}) + return false + }) + + return &types.GenesisState{ + Params: keeper.GetParams(ctx), + LastTotalPower: keeper.GetLastTotalPower(ctx), + LastValidatorPowers: lastValidatorPowers, + Validators: keeper.GetAllValidators(ctx), + Delegations: keeper.GetAllDelegations(ctx), + UnbondingDelegations: unbondingDelegations, + Redelegations: redelegations, + Exported: true, + } } // WriteValidators returns a slice of bonded genesis validators. diff --git a/x/staking/keeper/delegation.go b/x/staking/keeper/delegation.go index d2f1f373e7a1..7e37f4c9eb50 100644 --- a/x/staking/keeper/delegation.go +++ b/x/staking/keeper/delegation.go @@ -19,7 +19,8 @@ import ( // GetDelegation returns a specific delegation. func (k Keeper) GetDelegation(ctx sdk.Context, - delAddr sdk.AccAddress, valAddr sdk.ValAddress) (delegation types.Delegation, found bool) { + delAddr sdk.AccAddress, valAddr sdk.ValAddress, +) (delegation types.Delegation, found bool) { store := ctx.KVStore(k.storeKey) key := types.GetDelegationKey(delAddr, valAddr) @@ -91,7 +92,8 @@ func (k Keeper) GetValidatorDelegations(ctx sdk.Context, valAddr sdk.ValAddress) // GetDelegatorDelegations returns a given amount of all the delegations from a // delegator. func (k Keeper) GetDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress, - maxRetrieve uint16) (delegations []types.Delegation) { + maxRetrieve uint16, +) (delegations []types.Delegation) { delegations = make([]types.Delegation, maxRetrieve) i := 0 @@ -107,10 +109,7 @@ func (k Keeper) GetDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddres // SetDelegation sets a delegation. func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { - delegatorAddress, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress) - if err != nil { - return err - } + delegatorAddress := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) store := ctx.KVStore(k.storeKey) b := types.MustMarshalDelegation(k.cdc, delegation) @@ -119,19 +118,17 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) { // RemoveDelegation removes a delegation. func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) { - delegatorAddress, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress) - if err != nil { - return err - } + delegatorAddress := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) - // TODO: Consider calling hooks outside of the store wrapper functions, it's unobvious. - if err := k.Hooks().BeforeDelegationRemoved(ctx, delegatorAddress, valAddr); err != nil { - return err - } + k.BeforeDelegationRemoved(ctx, delegatorAddress, delegation.GetValidatorAddr()) + store := ctx.KVStore(k.storeKey) + store.Delete(types.GetDelegationKey(delegatorAddress, delegation.GetValidatorAddr())) +} // GetUnbondingDelegations returns a given amount of all the delegator unbonding-delegations. func (k Keeper) GetUnbondingDelegations(ctx sdk.Context, delegator sdk.AccAddress, - maxRetrieve uint16) (unbondingDelegations []types.UnbondingDelegation) { + maxRetrieve uint16, +) (unbondingDelegations []types.UnbondingDelegation) { unbondingDelegations = make([]types.UnbondingDelegation, maxRetrieve) return k.DelegationsByValidator.Remove(ctx, collections.Join(sdk.ValAddress(valAddr), sdk.AccAddress(delegatorAddress))) @@ -364,7 +361,8 @@ func (k Keeper) IterateDelegatorRedelegations(ctx sdk.Context, delegator sdk.Acc // HasMaxUnbondingDelegationEntries - check if unbonding delegation has maximum number of entries. func (k Keeper) HasMaxUnbondingDelegationEntries(ctx sdk.Context, - delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) bool { + delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress, +) bool { ubd, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) if !found { return false @@ -379,15 +377,11 @@ func (k Keeper) HasMaxUnbondingDelegationEntries(ctx sdk.Context, // SetUnbondingDelegation sets the unbonding delegation and associated index. func (k Keeper) SetUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { - delegatorAddress, err := sdk.AccAddressFromBech32(ubd.DelegatorAddress) - if err != nil { - return err - } - valAddr, err := k.validatorAddressCodec.StringToBytes(ubd.ValidatorAddress) - if err != nil { - return err - } - err = k.UnbondingDelegations.Set(ctx, collections.Join(delAddr, valAddr), ubd) + delegatorAddress := sdk.MustAccAddressFromBech32(ubd.DelegatorAddress) + + store := ctx.KVStore(k.storeKey) + bz := types.MustMarshalUBD(k.cdc, ubd) + addr, err := sdk.ValAddressFromBech32(ubd.ValidatorAddress) if err != nil { return err } @@ -397,15 +391,10 @@ func (k Keeper) SetUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDeleg // RemoveUnbondingDelegation removes the unbonding delegation object and associated index. func (k Keeper) RemoveUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDelegation) { - delegatorAddress, err := sdk.AccAddressFromBech32(ubd.DelegatorAddress) - if err != nil { - return err - } - valAddr, err := k.validatorAddressCodec.StringToBytes(ubd.ValidatorAddress) - if err != nil { - return err - } - err = k.UnbondingDelegations.Remove(ctx, collections.Join(delAddr, valAddr)) + delegatorAddress := sdk.MustAccAddressFromBech32(ubd.DelegatorAddress) + + store := ctx.KVStore(k.storeKey) + addr, err := sdk.ValAddressFromBech32(ubd.ValidatorAddress) if err != nil { return err } @@ -479,7 +468,8 @@ func (k Keeper) SetUBDQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys // InsertUBDQueue inserts an unbonding delegation to the appropriate timeslice // in the unbonding queue. func (k Keeper) InsertUBDQueue(ctx sdk.Context, ubd types.UnbondingDelegation, - completionTime time.Time) { + completionTime time.Time, +) { dvPair := types.DVPair{DelegatorAddress: ubd.DelegatorAddress, ValidatorAddress: ubd.ValidatorAddress} timeSlice, err := k.GetUBDQueueTimeSlice(ctx, completionTime) @@ -530,7 +520,8 @@ func (k Keeper) DequeueAllMatureUBDQueue(ctx sdk.Context, currTime time.Time) (m // GetRedelegations returns a given amount of all the delegator redelegations. func (k Keeper) GetRedelegations(ctx sdk.Context, delegator sdk.AccAddress, - maxRetrieve uint16) (redelegations []types.Redelegation) { + maxRetrieve uint16, +) (redelegations []types.Redelegation) { redelegations = make([]types.Redelegation, maxRetrieve) i := 0 @@ -553,7 +544,8 @@ func (k Keeper) GetRedelegations(ctx sdk.Context, delegator sdk.AccAddress, // GetRedelegation returns a redelegation. func (k Keeper) GetRedelegation(ctx sdk.Context, - delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) (red types.Redelegation, found bool) { + delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, +) (red types.Redelegation, found bool) { store := ctx.KVStore(k.storeKey) key := types.GetREDKey(delAddr, valSrcAddr, valDstAddr) @@ -586,7 +578,8 @@ func (k Keeper) GetRedelegationsFromSrcValidator(ctx sdk.Context, valAddr sdk.Va // HasReceivingRedelegation checks if validator is receiving a redelegation. func (k Keeper) HasReceivingRedelegation(ctx sdk.Context, - delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) bool { + delAddr sdk.AccAddress, valDstAddr sdk.ValAddress, +) bool { store := ctx.KVStore(k.storeKey) prefix := types.GetREDsByDelToValDstIndexKey(delAddr, valDstAddr) @@ -599,7 +592,8 @@ func (k Keeper) HasReceivingRedelegation(ctx sdk.Context, // HasMaxRedelegationEntries checks if redelegation has maximum number of entries. func (k Keeper) HasMaxRedelegationEntries(ctx sdk.Context, delegatorAddr sdk.AccAddress, validatorSrcAddr, - validatorDstAddr sdk.ValAddress) bool { + validatorDstAddr sdk.ValAddress, +) bool { red, found := k.GetRedelegation(ctx, delegatorAddr, validatorSrcAddr, validatorDstAddr) if !found { return false @@ -610,10 +604,7 @@ func (k Keeper) HasMaxRedelegationEntries(ctx sdk.Context, // SetRedelegation set a redelegation and associated index. func (k Keeper) SetRedelegation(ctx sdk.Context, red types.Redelegation) { - delegatorAddress, err := sdk.AccAddressFromBech32(red.DelegatorAddress) - if err != nil { - return err - } + delegatorAddress := sdk.MustAccAddressFromBech32(red.DelegatorAddress) valSrcAddr, err := k.validatorAddressCodec.StringToBytes(red.ValidatorSrcAddress) if err != nil { @@ -640,18 +631,13 @@ func (k Keeper) SetRedelegation(ctx sdk.Context, red types.Redelegation) { func (k Keeper) SetRedelegationEntry(ctx sdk.Context, delegatorAddr sdk.AccAddress, validatorSrcAddr, validatorDstAddr sdk.ValAddress, creationHeight int64, - minTime time.Time, balance math.Int, - sharesSrc, sharesDst math.LegacyDec, -) (types.Redelegation, error) { - id, err := k.IncrementUnbondingID(ctx) - if err != nil { - return types.Redelegation{}, err - } - - red, err := k.Redelegations.Get(ctx, collections.Join3(delegatorAddr.Bytes(), validatorSrcAddr.Bytes(), validatorDstAddr.Bytes())) - if err == nil { - red.AddEntry(creationHeight, minTime, balance, sharesDst, id) - } else if errors.Is(err, collections.ErrNotFound) { + minTime time.Time, balance sdk.Int, + sharesSrc, sharesDst sdk.Dec, +) types.Redelegation { + red, found := k.GetRedelegation(ctx, delegatorAddr, validatorSrcAddr, validatorDstAddr) + if found { + red.AddEntry(creationHeight, minTime, balance, sharesDst) + } else { red = types.NewRedelegation(delegatorAddr, validatorSrcAddr, validatorDstAddr, creationHeight, minTime, balance, sharesDst, id, k.validatorAddressCodec, k.authKeeper.AddressCodec()) } else { @@ -692,12 +678,10 @@ func (k Keeper) IterateRedelegations(ctx sdk.Context, fn func(index int64, red t // RemoveRedelegation removes a redelegation object and associated index. func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) { - delegatorAddress, err := sdk.AccAddressFromBech32(red.DelegatorAddress) - if err != nil { - return err - } + delegatorAddress := sdk.MustAccAddressFromBech32(red.DelegatorAddress) - valSrcAddr, err := k.validatorAddressCodec.StringToBytes(red.ValidatorSrcAddress) + store := ctx.KVStore(k.storeKey) + valSrcAddr, err := sdk.ValAddressFromBech32(red.ValidatorSrcAddress) if err != nil { return err } @@ -743,7 +727,8 @@ func (k Keeper) SetRedelegationQueueTimeSlice(ctx sdk.Context, timestamp time.Ti // InsertRedelegationQueue insert an redelegation delegation to the appropriate // timeslice in the redelegation queue. func (k Keeper) InsertRedelegationQueue(ctx sdk.Context, red types.Redelegation, - completionTime time.Time) { + completionTime time.Time, +) { timeSlice := k.GetRedelegationQueueTimeSlice(ctx, completionTime) dvvTriplet := types.DVVTriplet{ DelegatorAddress: red.DelegatorAddress, @@ -824,9 +809,7 @@ func (k Keeper) Delegate( return math.LegacyZeroDec(), err } - if err != nil { - return math.LegacyZeroDec(), err - } + delegatorAddress := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) // if subtractAccount is true then we are // performing a delegation and not a redelegation, thus the source tokens are diff --git a/x/staking/keeper/slash.go b/x/staking/keeper/slash.go index c7623d6b5c37..06943f835da2 100644 --- a/x/staking/keeper/slash.go +++ b/x/staking/keeper/slash.go @@ -374,12 +374,7 @@ func (k Keeper) SlashRedelegation(ctx context.Context, srcValidator types.Valida return math.ZeroInt(), err } - sharesToUnbond, err := dstVal.SharesFromTokensTruncated(slashAmount) - if sharesToUnbond.IsZero() { - continue - } else if err != nil { - return math.ZeroInt(), err - } + delegatorAddress := sdk.MustAccAddressFromBech32(redelegation.DelegatorAddress) // Delegations can be dynamic hence need to be looked up on every redelegation entry loop. delegation, err := k.Delegations.Get(ctx, collections.Join(sdk.AccAddress(delegatorAddress), sdk.ValAddress(valDstAddr))) diff --git a/x/staking/keeper/val_state_change.go b/x/staking/keeper/val_state_change.go index 867dc89dd5cb..e46321cf0965 100644 --- a/x/staking/keeper/val_state_change.go +++ b/x/staking/keeper/val_state_change.go @@ -56,10 +56,7 @@ func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]appmodule.Validato if err != nil { return nil, err } - delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(dvPair.DelegatorAddress) - if err != nil { - return nil, err - } + delegatorAddress := sdk.MustAccAddressFromBech32(dvPair.DelegatorAddress) balances, err := k.CompleteUnbonding(ctx, delegatorAddress, addr) if err != nil { @@ -91,10 +88,7 @@ func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]appmodule.Validato if err != nil { return nil, err } - delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(dvvTriplet.DelegatorAddress) - if err != nil { - return nil, err - } + delegatorAddress := sdk.MustAccAddressFromBech32(dvvTriplet.DelegatorAddress) balances, err := k.CompleteRedelegation( ctx, diff --git a/x/staking/types/delegation.go b/x/staking/types/delegation.go index fad9ae19ab76..725651490d75 100644 --- a/x/staking/types/delegation.go +++ b/x/staking/types/delegation.go @@ -46,8 +46,17 @@ func UnmarshalDelegation(cdc codec.BinaryCodec, value []byte) (delegation Delega return delegation, err } -func (d Delegation) GetDelegatorAddr() string { - return d.DelegatorAddress +func (d Delegation) GetDelegatorAddr() sdk.AccAddress { + delAddr := sdk.MustAccAddressFromBech32(d.DelegatorAddress) + + return delAddr +} +func (d Delegation) GetValidatorAddr() sdk.ValAddress { + addr, err := sdk.ValAddressFromBech32(d.ValidatorAddress) + if err != nil { + panic(err) + } + return addr } func (d Delegation) GetValidatorAddr() string {