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

feat(state): enable fee granting #3304

Merged
merged 11 commits into from
Apr 16, 2024
83 changes: 83 additions & 0 deletions nodebuilder/state/cmd/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import (
"github.com/celestiaorg/celestia-node/state"
)

var (
amount uint64
)

func init() {
Cmd.AddCommand(
accountAddressCmd,
Expand All @@ -26,6 +30,16 @@ func init() {
queryDelegationCmd,
queryUnbondingCmd,
queryRedelegationCmd,
grantFeeCmd,
revokeGrantFeeCmd,
)

grantFeeCmd.PersistentFlags().Uint64Var(
&amount,
"amount",
0,
"specifies the spend limit(in utia) for the grantee.\n"+
"The default value is 0 which means the grantee does not have a spend limit.",
)
vgonkivs marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down Expand Up @@ -402,6 +416,75 @@ var queryRedelegationCmd = &cobra.Command{
},
}

var grantFeeCmd = &cobra.Command{
Use: "grant-fee [granteeAddress] [fee] [gasLimit]",
Short: "Grant an allowance to a specified grantee account to pay the fees for their transactions.\n" +
vgonkivs marked this conversation as resolved.
Show resolved Hide resolved
"Grantee can spend any amount of tokens in case the spend limit is not set.",
vgonkivs marked this conversation as resolved.
Show resolved Hide resolved
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
client, err := cmdnode.ParseClientFromCtx(cmd.Context())
if err != nil {
return err
}
defer client.Close()

granteeAddr, err := parseAddressFromString(args[0])
if err != nil {
return fmt.Errorf("error parsing an address:%v", err)
}

fee, err := strconv.ParseInt(args[1], 10, 64)
if err != nil {
return fmt.Errorf("error parsing a fee:%v", err)
}
gasLimit, err := strconv.ParseUint(args[2], 10, 64)
if err != nil {
return fmt.Errorf("error parsing a gas limit:%v", err)
}

txResponse, err := client.State.GrantFee(
cmd.Context(),
granteeAddr.Address.(state.AccAddress),
math.NewInt(int64(amount)), math.NewInt(fee), gasLimit,
)
return cmdnode.PrintOutput(txResponse, err, nil)
},
}

var revokeGrantFeeCmd = &cobra.Command{
Use: "revoke-grant-fee [granteeAddress] [fee] [gasLimit]",
Short: "Removes permission for grantee to submit PFB transactions which will be paid by granter.",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
client, err := cmdnode.ParseClientFromCtx(cmd.Context())
if err != nil {
return err
}
defer client.Close()

granteeAddr, err := parseAddressFromString(args[0])
if err != nil {
return fmt.Errorf("error parsing an address:%v", err)
}

fee, err := strconv.ParseInt(args[1], 10, 64)
if err != nil {
return fmt.Errorf("error parsing a fee:%v", err)
}
gasLimit, err := strconv.ParseUint(args[2], 10, 64)
if err != nil {
return fmt.Errorf("error parsing a gas limit:%v", err)
}

txResponse, err := client.State.RevokeGrantFee(
cmd.Context(),
granteeAddr.Address.(state.AccAddress),
math.NewInt(fee), gasLimit,
)
return cmdnode.PrintOutput(txResponse, err, nil)
},
}

func parseAddressFromString(addrStr string) (state.Address, error) {
var address state.Address
err := address.UnmarshalJSON([]byte(addrStr))
Expand Down
4 changes: 4 additions & 0 deletions nodebuilder/state/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package state

import (
"github.com/cosmos/cosmos-sdk/crypto/keyring"

"github.com/celestiaorg/celestia-node/state"
)

var defaultKeyringBackend = keyring.BackendTest
Expand All @@ -11,12 +13,14 @@ var defaultKeyringBackend = keyring.BackendTest
type Config struct {
KeyringAccName string
KeyringBackend string
GranterAddress state.AccAddress
}

func DefaultConfig() Config {
return Config{
KeyringAccName: "",
KeyringBackend: defaultKeyringBackend,
GranterAddress: state.AccAddress{},
}
}

Expand Down
7 changes: 4 additions & 3 deletions nodebuilder/state/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ func coreAccessor(
signer *apptypes.KeyringSigner,
sync *sync.Syncer[*header.ExtendedHeader],
fraudServ libfraud.Service[*header.ExtendedHeader],
opts ...state.Option,
) (*state.CoreAccessor, Module, *modfraud.ServiceBreaker[*state.CoreAccessor, *header.ExtendedHeader]) {
ca := state.NewCoreAccessor(signer, sync, corecfg.IP, corecfg.RPCPort, corecfg.GRPCPort)

return ca, ca, &modfraud.ServiceBreaker[*state.CoreAccessor, *header.ExtendedHeader]{
ca := state.NewCoreAccessor(signer, sync, corecfg.IP, corecfg.RPCPort, corecfg.GRPCPort, opts...)
sBreaker := &modfraud.ServiceBreaker[*state.CoreAccessor, *header.ExtendedHeader]{
Service: ca,
FraudType: byzantine.BadEncoding,
FraudServ: fraudServ,
}
return ca, ca, sBreaker
}
13 changes: 13 additions & 0 deletions nodebuilder/state/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ package state
import (
"fmt"

sdktypes "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
)

var (
keyringAccNameFlag = "keyring.accname"
keyringBackendFlag = "keyring.backend"

granterAddressFlag = "granter.address"
)

// Flags gives a set of hardcoded State flags.
Expand All @@ -21,6 +24,7 @@ func Flags() *flag.FlagSet {
flags.String(keyringBackendFlag, defaultKeyringBackend, fmt.Sprintf("Directs node's keyring signer to use the given "+
"backend. Default is %s.", defaultKeyringBackend))

flags.String(granterAddressFlag, "", "Account address that will pay for all transactions submitted from the node.")
return flags
}

Expand All @@ -32,4 +36,13 @@ func ParseFlags(cmd *cobra.Command, cfg *Config) {
}

cfg.KeyringBackend = cmd.Flag(keyringBackendFlag).Value.String()

addr := cmd.Flag(granterAddressFlag).Value.String()
if addr != "" {
sdkAddress, err := sdktypes.AccAddressFromBech32(addr)
if err != nil {
panic(err)
vgonkivs marked this conversation as resolved.
Show resolved Hide resolved
}
cfg.GranterAddress = sdkAddress
}
}
30 changes: 30 additions & 0 deletions nodebuilder/state/mocks/api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion nodebuilder/state/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import (
logging "github.com/ipfs/go-log/v2"
"go.uber.org/fx"

apptypes "github.com/celestiaorg/celestia-app/x/blob/types"
libfraud "github.com/celestiaorg/go-fraud"
"github.com/celestiaorg/go-header/sync"

"github.com/celestiaorg/celestia-node/header"
"github.com/celestiaorg/celestia-node/libs/fxutil"
"github.com/celestiaorg/celestia-node/nodebuilder/core"
Expand All @@ -24,9 +28,16 @@ func ConstructModule(tp node.Type, cfg *Config, coreCfg *core.Config) fx.Option

baseComponents := fx.Options(
fx.Supply(*cfg),
fx.Supply(cfg.GranterAddress),
vgonkivs marked this conversation as resolved.
Show resolved Hide resolved
fx.Error(cfgErr),
fxutil.ProvideIf(coreCfg.IsEndpointConfigured(), fx.Annotate(
renaynay marked this conversation as resolved.
Show resolved Hide resolved
coreAccessor,
func(
signer *apptypes.KeyringSigner,
sync *sync.Syncer[*header.ExtendedHeader],
fraudServ libfraud.Service[*header.ExtendedHeader],
) (*state.CoreAccessor, Module, *modfraud.ServiceBreaker[*state.CoreAccessor, *header.ExtendedHeader]) {
return coreAccessor(*coreCfg, signer, sync, fraudServ, state.WithGranter(cfg.GranterAddress))
},
fx.OnStart(func(ctx context.Context,
breaker *modfraud.ServiceBreaker[*state.CoreAccessor, *header.ExtendedHeader]) error {
return breaker.Start(ctx)
Expand Down
48 changes: 48 additions & 0 deletions nodebuilder/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,21 @@ type Module interface {
srcValAddr,
dstValAddr state.ValAddress,
) (*types.QueryRedelegationsResponse, error)

GrantFee(
ctx context.Context,
grantee state.AccAddress,
amount,
fee state.Int,
gasLim uint64,
) (*state.TxResponse, error)

RevokeGrantFee(
ctx context.Context,
grantee state.AccAddress,
fee state.Int,
gasLim uint64,
) (*state.TxResponse, error)
}

// API is a wrapper around Module for the RPC.
Expand Down Expand Up @@ -160,6 +175,20 @@ type API struct {
srcValAddr,
dstValAddr state.ValAddress,
) (*types.QueryRedelegationsResponse, error) `perm:"read"`
GrantFee func(
ctx context.Context,
grantee state.AccAddress,
amount,
fee state.Int,
gasLim uint64,
) (*state.TxResponse, error) `perm:"write"`

RevokeGrantFee func(
ctx context.Context,
grantee state.AccAddress,
fee state.Int,
gasLim uint64,
) (*state.TxResponse, error) `perm:"write"`
}
}

Expand Down Expand Up @@ -256,3 +285,22 @@ func (api *API) QueryRedelegations(
func (api *API) Balance(ctx context.Context) (*state.Balance, error) {
return api.Internal.Balance(ctx)
}

func (api *API) GrantFee(
ctx context.Context,
grantee state.AccAddress,
amount,
fee state.Int,
gasLim uint64,
) (*state.TxResponse, error) {
return api.Internal.GrantFee(ctx, grantee, amount, fee, gasLim)
}

func (api *API) RevokeGrantFee(
ctx context.Context,
grantee state.AccAddress,
fee state.Int,
gasLim uint64,
) (*state.TxResponse, error) {
return api.Internal.RevokeGrantFee(ctx, grantee, fee, gasLim)
}
19 changes: 19 additions & 0 deletions nodebuilder/state/stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,22 @@ func (s stubbedStateModule) QueryRedelegations(
) (*types.QueryRedelegationsResponse, error) {
return nil, ErrNoStateAccess
}

func (s stubbedStateModule) GrantFee(
_ context.Context,
_ state.AccAddress,
_,
_ state.Int,
_ uint64,
) (*state.TxResponse, error) {
return nil, ErrNoStateAccess
}

func (s stubbedStateModule) RevokeGrantFee(
_ context.Context,
_ state.AccAddress,
_ state.Int,
_ uint64,
) (*state.TxResponse, error) {
return nil, ErrNoStateAccess
}
Loading
Loading