Skip to content

Commit

Permalink
feat(x/photon): validate fee ante decorator (#54)
Browse files Browse the repository at this point in the history
Relates to #44 

This PR adds a `sdk.AnteDecorator` implementation in `x/photon/ante` and
adds it to the list of the app ante decorators. This new ante decorator
ensures that photon is the fee token or returns an error. Exceptions are
possible like if the transaction's messages type URL are present in a
new parameter of the photon module `txFeeExceptions`.

Some significant changes have been made to the e2e tests to make them
compatible with this conditions.

`uatone` has also been put in a constant to avoid repetition (in
`app/params` package)
  • Loading branch information
tbruyelle authored Nov 28, 2024
1 parent 830ae39 commit 4563e66
Show file tree
Hide file tree
Showing 32 changed files with 822 additions and 227 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ start-localnet-ci: build
./build/atomoned genesis add-genesis-account user 1000000000uatone --home ~/.atomoned-liveness --keyring-backend test
./build/atomoned genesis gentx val 1000000000uatone --home ~/.atomoned-liveness --chain-id liveness
./build/atomoned genesis collect-gentxs --home ~/.atomoned-liveness
sed -i.bak'' 's/minimum-gas-prices = ""/minimum-gas-prices = "0uatone"/' ~/.atomoned-liveness/config/app.toml
sed -i.bak'' 's/minimum-gas-prices = ""/minimum-gas-prices = "0.001uatone,0.001uphoton"/' ~/.atomoned-liveness/config/app.toml
./build/atomoned start --home ~/.atomoned-liveness --x-crisis-skip-assert-invariants

.PHONY: start-localnet-ci
Expand Down
8 changes: 7 additions & 1 deletion ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"

atomoneerrors "github.com/atomone-hub/atomone/types/errors"
photonante "github.com/atomone-hub/atomone/x/photon/ante"
photonkeeper "github.com/atomone-hub/atomone/x/photon/keeper"
)

// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC
Expand All @@ -21,6 +23,7 @@ type HandlerOptions struct {
Codec codec.BinaryCodec
IBCkeeper *ibckeeper.Keeper
StakingKeeper *stakingkeeper.Keeper
PhotonKeeper *photonkeeper.Keeper
TxFeeChecker ante.TxFeeChecker
}

Expand All @@ -37,10 +40,12 @@ func NewAnteHandler(opts HandlerOptions) (sdk.AnteHandler, error) {
if opts.IBCkeeper == nil {
return nil, errorsmod.Wrap(atomoneerrors.ErrLogic, "IBC keeper is required for AnteHandler")
}

if opts.StakingKeeper == nil {
return nil, errorsmod.Wrap(atomoneerrors.ErrNotFound, "staking param store is required for AnteHandler")
}
if opts.PhotonKeeper == nil {
return nil, errorsmod.Wrap(atomoneerrors.ErrNotFound, "photon keeper is required for AnteHandler")
}

sigGasConsumer := opts.SigGasConsumer
if sigGasConsumer == nil {
Expand All @@ -54,6 +59,7 @@ func NewAnteHandler(opts HandlerOptions) (sdk.AnteHandler, error) {
ante.NewValidateMemoDecorator(opts.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(opts.AccountKeeper),
NewGovVoteDecorator(opts.Codec, opts.StakingKeeper),
photonante.NewValidateFeeDecorator(opts.PhotonKeeper),
ante.NewDeductFeeDecorator(opts.AccountKeeper, opts.BankKeeper, opts.FeegrantKeeper, opts.TxFeeChecker),
ante.NewSetPubKeyDecorator(opts.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
ante.NewValidateSigCountDecorator(opts.AccountKeeper),
Expand Down
4 changes: 3 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,15 @@ import (
"github.com/atomone-hub/atomone/app/keepers"
"github.com/atomone-hub/atomone/app/params"
"github.com/atomone-hub/atomone/app/upgrades"
v2 "github.com/atomone-hub/atomone/app/upgrades/v2"
govtypes "github.com/atomone-hub/atomone/x/gov/types"
)

var (
// DefaultNodeHome default home directories for the application daemon
DefaultNodeHome string

Upgrades = []upgrades.Upgrade{}
Upgrades = []upgrades.Upgrade{v2.Upgrade}
)

var (
Expand Down Expand Up @@ -221,6 +222,7 @@ func NewAtomOneApp(
Codec: appCodec,
IBCkeeper: app.IBCKeeper,
StakingKeeper: app.StakingKeeper,
PhotonKeeper: app.PhotonKeeper,
// If TxFeeChecker is nil the default ante TxFeeChecker is used
TxFeeChecker: nil,
},
Expand Down
20 changes: 20 additions & 0 deletions app/params/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package params

const (
BondDenom = "uatone"

Bech32PrefixAccAddr = "atone"
)

var (
// Bech32PrefixAccPub defines the Bech32 prefix of an account's public key.
Bech32PrefixAccPub = Bech32PrefixAccAddr + "pub"
// Bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address.
Bech32PrefixValAddr = Bech32PrefixAccAddr + "valoper"
// Bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key.
Bech32PrefixValPub = Bech32PrefixAccAddr + "valoperpub"
// Bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address.
Bech32PrefixConsAddr = Bech32PrefixAccAddr + "valcons"
// Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key.
Bech32PrefixConsPub = Bech32PrefixAccAddr + "valconspub"
)
7 changes: 0 additions & 7 deletions app/params/params.go

This file was deleted.

23 changes: 23 additions & 0 deletions app/upgrades/v2/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package v2

import (
store "github.com/cosmos/cosmos-sdk/store/types"

"github.com/atomone-hub/atomone/app/upgrades"
photontypes "github.com/atomone-hub/atomone/x/photon/types"
)

const (
UpgradeName = "v2"
)

var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
CreateUpgradeHandler: CreateUpgradeHandler,
StoreUpgrades: store.StoreUpgrades{
Added: []string{
// new module added in v2
photontypes.ModuleName,
},
},
}
66 changes: 66 additions & 0 deletions app/upgrades/v2/upgrades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package v2

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"

"github.com/atomone-hub/atomone/app/keepers"
)

// CreateUpgradeHandler returns a upgrade handler for AtomOne v2
// which executes the following migrations:
// - add new denom metadata for photon in the bank module store.
func CreateUpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
keepers *keepers.AppKeepers,
) upgradetypes.UpgradeHandler {
return func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
ctx.Logger().Info("Starting module migrations...")
// RunMigrations will detect the add of the photon module, will initiate
// its genesis and will fill the versionMap with its consensus version.
vm, err := mm.RunMigrations(ctx, configurator, vm)
if err != nil {
return vm, err
}
// Add the photon denom metadata to the bank module store
setPhotonDenomMetadata(ctx, keepers.BankKeeper)
ctx.Logger().Info("Upgrade complete")
return vm, nil
}
}

func setPhotonDenomMetadata(ctx sdk.Context, bk bankkeeper.Keeper) {
ctx.Logger().Info("Adding photon denom metadata...")
bk.SetDenomMetaData(ctx, banktypes.Metadata{
Base: "uphoton",
Display: "photon",
Name: "AtomOne Photon",
Symbol: "PHOTON",
Description: "The fee token of AtomOne Hub",
DenomUnits: []*banktypes.DenomUnit{
{
Denom: "uphoton",
Exponent: 0,
Aliases: []string{
"microphoton",
},
},
{
Denom: "mphoton",
Exponent: 3,
Aliases: []string{
"milliphoton",
},
},
{
Denom: "photon",
Exponent: 6,
},
},
})
ctx.Logger().Info("Photon denom metadata added")
}
3 changes: 2 additions & 1 deletion cmd/atomoned/cmd/bech32_convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/spf13/cobra"

appparams "github.com/atomone-hub/atomone/app/params"
addressutil "github.com/atomone-hub/atomone/pkg/address"
)

Expand Down Expand Up @@ -41,7 +42,7 @@ Example:
},
}

cmd.Flags().StringP(flagBech32Prefix, "p", "atone", "Bech32 Prefix to encode to")
cmd.Flags().StringP(flagBech32Prefix, "p", appparams.Bech32PrefixAccAddr, "Bech32 Prefix to encode to")

return cmd
}
Expand Down
23 changes: 4 additions & 19 deletions cmd/atomoned/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,14 @@ package cmd

import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

const (
Bech32PrefixAccAddr = "atone"
)

var (
// Bech32PrefixAccPub defines the Bech32 prefix of an account's public key.
Bech32PrefixAccPub = Bech32PrefixAccAddr + "pub"
// Bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address.
Bech32PrefixValAddr = Bech32PrefixAccAddr + "valoper"
// Bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key.
Bech32PrefixValPub = Bech32PrefixAccAddr + "valoperpub"
// Bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address.
Bech32PrefixConsAddr = Bech32PrefixAccAddr + "valcons"
// Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key.
Bech32PrefixConsPub = Bech32PrefixAccAddr + "valconspub"
appparams "github.com/atomone-hub/atomone/app/params"
)

func InitSDKConfig() {
cfg := sdk.GetConfig()
cfg.SetBech32PrefixForAccount(Bech32PrefixAccAddr, Bech32PrefixAccPub)
cfg.SetBech32PrefixForValidator(Bech32PrefixValAddr, Bech32PrefixValPub)
cfg.SetBech32PrefixForConsensusNode(Bech32PrefixConsAddr, Bech32PrefixConsPub)
cfg.SetBech32PrefixForAccount(appparams.Bech32PrefixAccAddr, appparams.Bech32PrefixAccPub)
cfg.SetBech32PrefixForValidator(appparams.Bech32PrefixValAddr, appparams.Bech32PrefixValPub)
cfg.SetBech32PrefixForConsensusNode(appparams.Bech32PrefixConsAddr, appparams.Bech32PrefixConsPub)
cfg.Seal()
}
6 changes: 5 additions & 1 deletion proto/atomone/photon/v1/photon.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ option go_package = "github.com/atomone-hub/atomone/x/photon/types";

// Params defines the parameters for the x/photon module.
message Params {
// mint photon or not
// Allow to mint photon or not
bool mint_disabled = 1;
// tx_fee_exceptions holds the msg type urls that are allowed to use some
// different tx fee coins than photon.
// A wildcard "*" can be used to allow all transactions to use any fee denom.
repeated string tx_fee_exceptions = 2;
}
23 changes: 19 additions & 4 deletions tests/e2e/e2e_bank_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (s *IntegrationTestSuite) testBankTokenTransfer() {
)

// alice sends tokens to bob
s.execBankSend(s.chainA, valIdx, alice.String(), bob.String(), tokenAmount.String(), standardFees.String(), false)
s.execBankSend(s.chainA, valIdx, alice.String(), bob.String(), tokenAmount.String(), false)

// check that the transfer was successful
s.Require().Eventually(
Expand All @@ -58,7 +58,7 @@ func (s *IntegrationTestSuite) testBankTokenTransfer() {
afterBobUAtoneBalance, err = getSpecificBalance(chainEndpoint, bob.String(), uatoneDenom)
s.Require().NoError(err)

decremented := beforeAliceUAtoneBalance.Sub(tokenAmount).Sub(standardFees).IsEqual(afterAliceUAtoneBalance)
decremented := beforeAliceUAtoneBalance.Sub(tokenAmount).IsEqual(afterAliceUAtoneBalance)
incremented := beforeBobUAtoneBalance.Add(tokenAmount).IsEqual(afterBobUAtoneBalance)

return decremented && incremented
Expand All @@ -71,7 +71,8 @@ func (s *IntegrationTestSuite) testBankTokenTransfer() {
beforeAliceUAtoneBalance, beforeBobUAtoneBalance = afterAliceUAtoneBalance, afterBobUAtoneBalance

// alice sends tokens to bob and charlie, at once
s.execBankMultiSend(s.chainA, valIdx, alice.String(), []string{bob.String(), charlie.String()}, tokenAmount.String(), standardFees.String(), false)
s.execBankMultiSend(s.chainA, valIdx, alice.String(),
[]string{bob.String(), charlie.String()}, tokenAmount.String(), false)

s.Require().Eventually(
func() bool {
Expand All @@ -85,7 +86,7 @@ func (s *IntegrationTestSuite) testBankTokenTransfer() {
s.Require().NoError(err)

// assert alice's account gets decremented the amount of tokens twice
decremented := beforeAliceUAtoneBalance.Sub(tokenAmount).Sub(tokenAmount).Sub(standardFees).IsEqual(afterAliceUAtoneBalance)
decremented := beforeAliceUAtoneBalance.Sub(tokenAmount).Sub(tokenAmount).IsEqual(afterAliceUAtoneBalance)
incremented := beforeBobUAtoneBalance.Add(tokenAmount).IsEqual(afterBobUAtoneBalance) &&
beforeCharlieUAtoneBalance.Add(tokenAmount).IsEqual(afterCharlieUAtoneBalance)

Expand All @@ -95,4 +96,18 @@ func (s *IntegrationTestSuite) testBankTokenTransfer() {
time.Second,
)
})

s.Run("send tokens with atone fees", func() {
var (
valIdx = 0
c = s.chainA
)
alice, _ := c.genesisAccounts[1].keyInfo.GetAddress()
bob, _ := c.genesisAccounts[2].keyInfo.GetAddress()

// alice sends tokens to bob should fail because doesn't use photons for the fees.
atoneFees := sdk.NewCoin(uatoneDenom, standardFees.Amount)
s.execBankSend(s.chainA, valIdx, alice.String(), bob.String(),
tokenAmount.String(), true, withKeyValue(flagFees, atoneFees))
})
}
5 changes: 2 additions & 3 deletions tests/e2e/e2e_distribution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ func (s *IntegrationTestSuite) testDistribution() {
delegatorAddress, _ := s.chainA.genesisAccounts[2].keyInfo.GetAddress()

newWithdrawalAddress, _ := s.chainA.genesisAccounts[3].keyInfo.GetAddress()
fees := sdk.NewCoin(uatoneDenom, sdk.NewInt(1000))

beforeBalance, err := getSpecificBalance(chainEndpoint, newWithdrawalAddress.String(), uatoneDenom)
s.Require().NoError(err)
if beforeBalance.IsNil() {
beforeBalance = sdk.NewCoin(uatoneDenom, sdk.NewInt(0))
}

s.execSetWithdrawAddress(s.chainA, 0, fees.String(), delegatorAddress.String(), newWithdrawalAddress.String(), atomoneHomePath)
s.execSetWithdrawAddress(s.chainA, 0, delegatorAddress.String(), newWithdrawalAddress.String(), atomoneHomePath)

// Verify
s.Require().Eventually(
Expand Down Expand Up @@ -76,7 +75,7 @@ func (s *IntegrationTestSuite) fundCommunityPool() {
beforeDistUatoneBalance = sdk.NewInt64Coin(uatoneDenom, 0)
}

s.execDistributionFundCommunityPool(s.chainA, 0, sender.String(), tokenAmount.String(), standardFees.String())
s.execDistributionFundCommunityPool(s.chainA, 0, sender.String(), tokenAmount.String())

s.Require().Eventually(
func() bool {
Expand Down
Loading

0 comments on commit 4563e66

Please sign in to comment.