diff --git a/CHANGELOG.md b/CHANGELOG.md index 0785257a06..48f16b8174 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/zkauth) [\#1239](https://github.com/Finschia/finschia-sdk/pull/1239) add CalculateAllInputsHash in ZKAuthInputs * (x/zkauth) [\#1275](https://github.com/Finschia/finschia-sdk/pull/1275) Ignore gas when zkauth * (x/zkauth) [\#1278](https://github.com/Finschia/finschia-sdk/pull/1278) Correct set of address +* (x/zkauth) [\#1279](https://github.com/Finschia/finschia-sdk/pull/1279) Deduct gas fee from zkauth address * (x/zkauth) [\#1280](https://github.com/Finschia/finschia-sdk/pull/1280) Fetch jwk considering goroutine exit ### Bug Fixes diff --git a/x/zkauth/ante/zkauth.go b/x/zkauth/ante/zkauth.go index 760bf840b7..a9f8700fe4 100644 --- a/x/zkauth/ante/zkauth.go +++ b/x/zkauth/ante/zkauth.go @@ -1,6 +1,8 @@ package ante import ( + "fmt" + "github.com/Finschia/finschia-sdk/crypto/types" sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" @@ -143,7 +145,7 @@ func NewZKAuthDeductFeeDecorator(ak authante.AccountKeeper, bankKeeper authtypes } func (zdf ZKAuthDeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { - isZKAuthTx, _, _, err := getZKAuthInfoFromTx(tx) + isZKAuthTx, zkMsgs, _, err := getZKAuthInfoFromTx(tx) if err != nil { return ctx, err } @@ -152,7 +154,64 @@ func (zdf ZKAuthDeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul return zdf.dfd.AnteHandle(ctx, tx, simulate, next) } - // Case of zkauth msg, does nothing in this case + // Almost no different from the implementation of zdf.dfd.AnteHandle, uses ZKauthAddress for feePayer. + feeTx, ok := tx.(sdk.FeeTx) + if !ok { + return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") + } + + if addr := zdf.ak.GetModuleAddress(authtypes.FeeCollectorName); addr.Empty() { + return ctx, fmt.Errorf("fee collector module account (%s) has not been set", authtypes.FeeCollectorName) + } + + fee := feeTx.GetFee() + // TODO: It is necessary to consider how to respond when multiple zkmsg are included in one tx. + signature := zkMsgs[0].GetZkAuthSignature() + feePayer, err := signature.GetZkAuthInputs().AccAddress() + if err != nil { + return ctx, err + } + feeGranter := feeTx.FeeGranter() + + deductFeesFrom := feePayer + + // if feegranter set deduct fee from feegranter account. + // this works with only when feegrant enabled. + if feeGranter != nil { + if zdf.feegrantKeeper == nil { + return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee grants are not enabled") + } else if !feeGranter.Equals(feePayer) { + err := zdf.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, fee, tx.GetMsgs()) + if err != nil { + return ctx, sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer) + } + } + + deductFeesFrom = feeGranter + } + + deductFeesFromAcc := zdf.ak.GetAccount(ctx, deductFeesFrom) + if deductFeesFromAcc == nil { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", deductFeesFrom) + } + + // deduct the fees + if !feeTx.GetFee().IsZero() { + err = authante.DeductFees(zdf.bankKeeper, ctx, deductFeesFromAcc, feeTx.GetFee()) + if err != nil { + return ctx, err + } + } + + events := sdk.Events{ + sdk.NewEvent( + sdk.EventTypeTx, + sdk.NewAttribute(sdk.AttributeKeyFee, fee.String()), + sdk.NewAttribute(sdk.AttributeKeyFeePayer, deductFeesFrom.String()), + ), + } + ctx.EventManager().EmitEvents(events) + return next(ctx, tx, simulate) } diff --git a/x/zkauth/ante/zkauth_test.go b/x/zkauth/ante/zkauth_test.go index 1d27856fa1..abf4a4502a 100644 --- a/x/zkauth/ante/zkauth_test.go +++ b/x/zkauth/ante/zkauth_test.go @@ -26,6 +26,8 @@ func TestNewDecorators(t *testing.T) { } accounts, err := f.CreateTestAccounts(2) require.NoError(t, err) + zkauthAddress, err := f.AddTestAccounts([]string{"link1g7ud63eqllj7zj4q7fkca5h7s223j78tyvr0e2cxuw4qyyaaf3usa64dqc"}) + require.NoError(t, err) // bank msg subMsg := &banktype.MsgSend{ @@ -50,6 +52,7 @@ func TestNewDecorators(t *testing.T) { err = f.TxBuilder.SetMsgs(msg) require.NoError(t, err) + f.TxBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("cony", sdk.NewInt(1000)))) ephPubKey, ok := new(big.Int).SetString("18948426102457371978524559226152399917062673825697601263047735920285791872240", 10) require.True(t, ok) pub := secp256k1.PubKey{Key: ephPubKey.Bytes()} @@ -62,4 +65,8 @@ func TestNewDecorators(t *testing.T) { }) require.NoError(t, err) } + + balance, err := f.BankKeeper.Balance(sdk.WrapSDKContext(f.Ctx), &banktype.QueryBalanceRequest{zkauthAddress[0].GetAddress().String(), "cony"}) + require.NoError(t, err) + require.Equal(t, sdk.NewInt(9999000), balance.Balance.Amount) } diff --git a/x/zkauth/testutil/keeper.go b/x/zkauth/testutil/keeper.go index fe1727eee8..053e592e13 100644 --- a/x/zkauth/testutil/keeper.go +++ b/x/zkauth/testutil/keeper.go @@ -22,6 +22,7 @@ import ( authtypes "github.com/Finschia/finschia-sdk/x/auth/types" banktypes "github.com/Finschia/finschia-sdk/x/bank/types" bankpluskeeper "github.com/Finschia/finschia-sdk/x/bankplus/keeper" + feegrant "github.com/Finschia/finschia-sdk/x/feegrant" feegrantkeeper "github.com/Finschia/finschia-sdk/x/feegrant/keeper" minttypes "github.com/Finschia/finschia-sdk/x/mint/types" "github.com/Finschia/finschia-sdk/x/zkauth/keeper" @@ -92,12 +93,12 @@ func ZkAuthKeeper(t testing.TB) TestApp { clientCtx := client.Context{}.WithTxConfig(encodingConfig.TxConfig) authKeeper := authkeeper.NewAccountKeeper( - appCodec, app.GetKey(types.StoreKey), app.GetSubspace(authtypes.ModuleName), + appCodec, app.GetKey(authtypes.StoreKey), app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms, ) - feeGrantKeeper := feegrantkeeper.NewKeeper(appCodec, app.GetKey(types.StoreKey), authKeeper) + feeGrantKeeper := feegrantkeeper.NewKeeper(appCodec, app.GetKey(feegrant.StoreKey), authKeeper) bankKeeper := bankpluskeeper.NewBaseKeeper( - appCodec, app.GetKey(types.StoreKey), authKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(), false) + appCodec, app.GetKey(banktypes.StoreKey), authKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(), false) testApp := TestApp{ Simapp: app,