From 604be7fed47bc3ee8c8d5bc50b3a0a5d4b2db45f Mon Sep 17 00:00:00 2001 From: yutianwu Date: Wed, 30 Aug 2023 14:25:50 +0800 Subject: [PATCH] feat: deposit the balance of the bank account to the payment account (#435) * feat: deposit balance of bank account to payment account * fix unit tests * delete unused code * fix comments * fix security alerts * update go.mod --- app/app.go | 2 +- app/upgrade.go | 22 ++++++++- deployment/localup/localup.sh | 1 + e2e/tests/payment_test.go | 63 ++++++++++++++++++++++++++ e2e/tests/storage_bill_test.go | 9 ++-- go.mod | 2 +- go.sum | 4 +- types/openapiutil/apiconsole.go | 10 +++- x/challenge/client/cli/tx_submit.go | 2 +- x/payment/keeper/msg_server_deposit.go | 25 +++++++--- x/payment/keeper/payment_account.go | 11 +++++ x/storage/client/cli/tx.go | 6 +-- 12 files changed, 137 insertions(+), 20 deletions(-) diff --git a/app/app.go b/app/app.go index 6fd5552d5..2ed197734 100644 --- a/app/app.go +++ b/app/app.go @@ -527,7 +527,7 @@ func New( encodingConfig.TxConfig), auth.NewAppModule(appCodec, app.AccountKeeper, nil, nil), authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), - bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, nil), + bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.PaymentKeeper, nil), feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, nil), slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil), diff --git a/app/upgrade.go b/app/upgrade.go index 439c85aa2..4f7624a26 100644 --- a/app/upgrade.go +++ b/app/upgrade.go @@ -2,6 +2,9 @@ package app import ( serverconfig "github.com/cosmos/cosmos-sdk/server/config" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig.Config) error { @@ -12,7 +15,7 @@ func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig. } // Register the upgrade handlers here - // app.registerPublicDelegationUpgradeHandler() + app.registerNagquUpgradeHandler() // app.register...() // ... return nil @@ -36,3 +39,20 @@ func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig. // }, // ) // } + +func (app *App) registerNagquUpgradeHandler() { + // Register the upgrade handler + app.UpgradeKeeper.SetUpgradeHandler(upgradetypes.Nagqu, + func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + app.Logger().Info("upgrade to ", plan.Name) + return fromVM, nil + }) + + // Register the upgrade initializer + app.UpgradeKeeper.SetUpgradeInitializer(upgradetypes.Nagqu, + func() error { + app.Logger().Info("Init Nagqu upgrade") + return nil + }, + ) +} diff --git a/deployment/localup/localup.sh b/deployment/localup/localup.sh index e6fa79d58..bee5fc4b6 100644 --- a/deployment/localup/localup.sh +++ b/deployment/localup/localup.sh @@ -154,6 +154,7 @@ function generate_genesis() { sed -i -e "s/src-chain-id = 1/src-chain-id = ${SRC_CHAIN_ID}/g" ${workspace}/.local/validator${i}/config/app.toml sed -i -e "s/dest-bsc-chain-id = 2/dest-bsc-chain-id = ${DEST_CHAIN_ID}/g" ${workspace}/.local/validator${i}/config/app.toml sed -i -e "s/snapshot-keep-recent = 2/snapshot-keep-recent = ${SNAPSHOT_KEEP_RECENT}/g" ${workspace}/.local/validator${i}/config/app.toml + echo -e '[[upgrade]]\nname = "Nagqu"\nheight = 1\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml sed -i -e "s/\"reserve_time\": \"15552000\"/\"reserve_time\": \"60\"/g" ${workspace}/.local/validator${i}/config/genesis.json sed -i -e "s/\"forced_settle_time\": \"86400\"/\"forced_settle_time\": \"30\"/g" ${workspace}/.local/validator${i}/config/genesis.json sed -i -e "s/172800s/${DEPOSIT_VOTE_PERIOD}/g" ${workspace}/.local/validator${i}/config/genesis.json diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index b2ba54738..e83567736 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -3,6 +3,7 @@ package tests import ( "bytes" "context" + "encoding/binary" "fmt" "math" "reflect" @@ -12,6 +13,7 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/types/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -375,6 +377,67 @@ func (s *PaymentTestSuite) TestDeposit_ActiveAccount() { s.Require().Equal(paymentAccountBNBNeeded.MulRaw(3), settledBalance.Add(paymentAccountStreamRecordAfter.StaticBalance.Add(paymentAccountStreamRecordAfter.BufferBalance))) } +func (s *PaymentTestSuite) TestDeposit_FromBankAccount() { + ctx := context.Background() + user := s.GenAndChargeAccounts(1, 1000000)[0] + userAddr := user.GetAddr().String() + var err error + + // derive payment account + paymentAccount := derivePaymentAccount(user.GetAddr(), 0) + // transfer BNB to derived payment account + msgSend := banktypes.NewMsgSend(user.GetAddr(), paymentAccount, sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, sdk.NewInt(1e18)), + )) + _ = s.SendTxBlock(user, msgSend) + + paymentBalanceBefore, err := s.Client.Balance(ctx, &banktypes.QueryBalanceRequest{ + Address: paymentAccount.String(), + Denom: s.Config.Denom, + }) + s.Require().NoError(err) + s.Require().Equal(sdk.NewInt(1e18).String(), paymentBalanceBefore.GetBalance().Amount.String()) + + // create payment account and deposit + msgCreatePaymentAccount := &paymenttypes.MsgCreatePaymentAccount{ + Creator: userAddr, + } + _ = s.SendTxBlock(user, msgCreatePaymentAccount) + paymentAccountsReq := &paymenttypes.QueryPaymentAccountsByOwnerRequest{Owner: userAddr} + paymentAccounts, err := s.Client.PaymentQueryClient.PaymentAccountsByOwner(ctx, paymentAccountsReq) + s.Require().NoError(err) + s.T().Logf("paymentAccounts %s", core.YamlString(paymentAccounts)) + paymentAddr := paymentAccounts.PaymentAccounts[0] + s.Require().Lenf(paymentAccounts.PaymentAccounts, 1, "paymentAccounts %s", core.YamlString(paymentAccounts)) + + // transfer BNB to payment account: should not success + msgSend = banktypes.NewMsgSend(user.GetAddr(), sdk.MustAccAddressFromHex(paymentAddr), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, sdk.NewInt(1e18)), + )) + s.SendTxBlockWithExpectErrorString(msgSend, user, "is not allowed to receive funds") + + // deposit BNB needed + msgDeposit := &paymenttypes.MsgDeposit{ + Creator: user.GetAddr().String(), + To: paymentAddr, + Amount: sdk.NewInt(1e18), // deposit more than needed + } + _ = s.SendTxBlock(user, msgDeposit) + + paymentBalanceAfter, err := s.Client.Balance(ctx, &banktypes.QueryBalanceRequest{ + Address: paymentAddr, + Denom: s.Config.Denom, + }) + s.Require().NoError(err) + s.Require().Equal(sdk.NewInt(0).String(), paymentBalanceAfter.GetBalance().Amount.String()) +} + +func derivePaymentAccount(owner sdk.AccAddress, index uint64) sdk.AccAddress { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, index) + return address.Derive(owner.Bytes(), b)[:sdk.EthAddressLength] +} + func (s *PaymentTestSuite) TestDeposit_ResumeInOneBlock() { ctx := context.Background() sp := s.PickStorageProvider() diff --git a/e2e/tests/storage_bill_test.go b/e2e/tests/storage_bill_test.go index 20b0352d0..640f67ee5 100644 --- a/e2e/tests/storage_bill_test.go +++ b/e2e/tests/storage_bill_test.go @@ -1712,7 +1712,6 @@ func (s *PaymentTestSuite) TestStorageBill_UpdatePaymentAddress() { // assertions streamAddresses[0] = paymentAccountAddr streamRecordsAfter = s.getStreamRecords(streamAddresses) - s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), readChargeRate) s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) @@ -2235,8 +2234,12 @@ func (s *PaymentTestSuite) CreatePaymentAccount(user keys.KeyManager, amount, de paymentAccountAddr := paymentAccounts.PaymentAccounts[len(paymentAccounts.PaymentAccounts)-1] // charge payment account paymentAcc := sdk.MustAccAddressFromHex(paymentAccountAddr) - msgSend := banktypes.NewMsgSend(user.GetAddr(), paymentAcc, []sdk.Coin{{Denom: "BNB", Amount: types.NewIntFromInt64WithDecimal(amount, decimal)}}) - s.SendTxBlock(user, msgSend) + msgDeposit := &paymenttypes.MsgDeposit{ + Creator: user.GetAddr().String(), + To: paymentAcc.String(), + Amount: types.NewIntFromInt64WithDecimal(amount, decimal), // deposit more than needed + } + s.SendTxBlock(user, msgDeposit) return paymentAccountAddr } diff --git a/go.mod b/go.mod index 3ab311262..9da09f09a 100644 --- a/go.mod +++ b/go.mod @@ -178,7 +178,7 @@ replace ( github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-cometbft v0.0.3 github.com/cometbft/cometbft-db => github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/bnb-chain/greenfield-cosmos-sdk v0.2.4 + github.com/cosmos/cosmos-sdk => github.com/bnb-chain/greenfield-cosmos-sdk v0.2.3-alpha.3.0.20230830024916-258a09e84d27 github.com/cosmos/iavl => github.com/bnb-chain/greenfield-iavl v0.20.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ) diff --git a/go.sum b/go.sum index 0795d07d4..0389e931a 100644 --- a/go.sum +++ b/go.sum @@ -163,8 +163,8 @@ github.com/bnb-chain/greenfield-cometbft v0.0.3 h1:tv8NMy3bzX/1urqXGQIIAZSLy83lo github.com/bnb-chain/greenfield-cometbft v0.0.3/go.mod h1:f35mk/r5ab6yvzlqEWZt68LfUje68sYgMpVlt2CUYMk= github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1 h1:XcWulGacHVRiSCx90Q8Y//ajOrLNBQWR/KDB89dy3cU= github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1/go.mod h1:ey1CiK4bYo1RBNJLRiVbYr5CMdSxci9S/AZRINLtppI= -github.com/bnb-chain/greenfield-cosmos-sdk v0.2.4 h1:09ST+MTEAyjyBSc4ZjZzHxpNLMnIIkZ518jJVRtrKFc= -github.com/bnb-chain/greenfield-cosmos-sdk v0.2.4/go.mod h1:y3hDhQhil5hMIhwBTpu07RZBF30ZITkoE+GHhVZChtY= +github.com/bnb-chain/greenfield-cosmos-sdk v0.2.3-alpha.3.0.20230830024916-258a09e84d27 h1:sqmAIC7IRqptGrwNPGQZuqDhcNQYpX1iUADGKMwa9RQ= +github.com/bnb-chain/greenfield-cosmos-sdk v0.2.3-alpha.3.0.20230830024916-258a09e84d27/go.mod h1:y3hDhQhil5hMIhwBTpu07RZBF30ZITkoE+GHhVZChtY= github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20230816082903-b48770f5e210 h1:GHPbV2bC+gmuO6/sG0Tm8oGal3KKSRlyE+zPscDjlA8= github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20230816082903-b48770f5e210/go.mod h1:vhsZxXE9tYJeYB5JR4hPhd6Pc/uPf7j1T8IJ7p9FdeM= github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20230816082903-b48770f5e210 h1:FLVOn4+OVbsKi2+YJX5kmD27/4dRu4FW7xCXFhzDO5s= diff --git a/types/openapiutil/apiconsole.go b/types/openapiutil/apiconsole.go index e3a1dc034..1bc64f7af 100644 --- a/types/openapiutil/apiconsole.go +++ b/types/openapiutil/apiconsole.go @@ -11,15 +11,21 @@ var index embed.FS // Handler returns a http handler that servers OpenAPI console for an OpenAPI spec at specURL. func Handler(title, specURL string) http.HandlerFunc { - t, _ := template.ParseFS(index, "index.tpl") + t, err := template.ParseFS(index, "index.tpl") + if err != nil { + panic(err) + } return func(w http.ResponseWriter, req *http.Request) { - _ = t.Execute(w, struct { + err := t.Execute(w, struct { Title string URL string }{ title, specURL, }) + if err != nil { + panic(err) + } } } diff --git a/x/challenge/client/cli/tx_submit.go b/x/challenge/client/cli/tx_submit.go index 92f54fa2a..9c83ed48b 100644 --- a/x/challenge/client/cli/tx_submit.go +++ b/x/challenge/client/cli/tx_submit.go @@ -45,7 +45,7 @@ func CmdSubmit() *cobra.Command { argSegmentIndex := uint64(0) if !argRandomIndex { - argSegmentIndex, err = strconv.ParseUint(args[4], 10, 64) + argSegmentIndex, err = strconv.ParseUint(args[4], 10, 32) if err != nil { return fmt.Errorf("segment-index %s not a valid uint, please input a valid segment-index", args[4]) } diff --git a/x/payment/keeper/msg_server_deposit.go b/x/payment/keeper/msg_server_deposit.go index 3ee98d4b2..51c9fcba0 100644 --- a/x/payment/keeper/msg_server_deposit.go +++ b/x/payment/keeper/msg_server_deposit.go @@ -4,6 +4,7 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/bnb-chain/greenfield/x/payment/types" ) @@ -14,11 +15,23 @@ func (k msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types // bank transfer creator := sdk.MustAccAddressFromHex(msg.Creator) to := sdk.MustAccAddressFromHex(msg.To) - coins := sdk.NewCoins(sdk.NewCoin(k.GetParams(ctx).FeeDenom, msg.Amount)) - err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, creator, types.ModuleName, coins) + depositAmount := msg.Amount + coinsToDeposit := sdk.NewCoins(sdk.NewCoin(k.GetParams(ctx).FeeDenom, depositAmount)) + err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, creator, types.ModuleName, coinsToDeposit) if err != nil { return nil, err } + if ctx.IsUpgraded(upgradetypes.Nagqu) && k.IsPaymentAccount(ctx, to) { + balanceOfToAccount := k.bankKeeper.GetBalance(ctx, to, k.GetParams(ctx).FeeDenom) + if balanceOfToAccount.IsPositive() { + err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, to, types.ModuleName, sdk.NewCoins(balanceOfToAccount)) + if err != nil { + return nil, err + } + depositAmount = depositAmount.Add(balanceOfToAccount.Amount) + } + } + // change payment record streamRecord, found := k.GetStreamRecord(ctx, to) @@ -30,12 +43,12 @@ func (k msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types } streamRecord.Account = msg.To streamRecord.CrudTimestamp = ctx.BlockTime().Unix() - streamRecord.StaticBalance = msg.Amount + streamRecord.StaticBalance = depositAmount k.SetStreamRecord(ctx, streamRecord) } else { if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE { // add static balance - change := types.NewDefaultStreamRecordChangeWithAddr(to).WithStaticBalanceChange(msg.Amount) + change := types.NewDefaultStreamRecordChangeWithAddr(to).WithStaticBalanceChange(depositAmount) err = k.UpdateStreamRecord(ctx, streamRecord, change) if err != nil { return nil, err @@ -43,7 +56,7 @@ func (k msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types k.SetStreamRecord(ctx, streamRecord) } else if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN { // deposit and try resume the account - err = k.TryResumeStreamRecord(ctx, streamRecord, msg.Amount) + err = k.TryResumeStreamRecord(ctx, streamRecord, depositAmount) if err != nil { return nil, err } @@ -56,7 +69,7 @@ func (k msgServer) Deposit(goCtx context.Context, msg *types.MsgDeposit) (*types event := types.EventDeposit{ From: creator.String(), To: to.String(), - Amount: msg.Amount, + Amount: depositAmount, } err = ctx.EventManager().EmitTypedEvents(&event) if err != nil { diff --git a/x/payment/keeper/payment_account.go b/x/payment/keeper/payment_account.go index 2e2f52a9f..4da5fd321 100644 --- a/x/payment/keeper/payment_account.go +++ b/x/payment/keeper/payment_account.go @@ -46,6 +46,17 @@ func (k Keeper) GetPaymentAccount( return val, true } +// IsPaymentAccount returns is the account address a payment account +func (k Keeper) IsPaymentAccount( + ctx sdk.Context, + addr sdk.AccAddress, +) bool { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.PaymentAccountKeyPrefix) + return store.Has(types.PaymentAccountKey( + addr, + )) +} + // GetAllPaymentAccount returns all paymentAccount func (k Keeper) GetAllPaymentAccount(ctx sdk.Context) (list []types.PaymentAccount) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.PaymentAccountKeyPrefix) diff --git a/x/storage/client/cli/tx.go b/x/storage/client/cli/tx.go index 6294c9ca3..b1a4bb830 100644 --- a/x/storage/client/cli/tx.go +++ b/x/storage/client/cli/tx.go @@ -899,7 +899,7 @@ func CmdMirrorBucket() *cobra.Command { if argDestChainId == "" { return fmt.Errorf("destination chain id should be provided") } - destChainId, err := strconv.ParseUint(argDestChainId, 10, 64) + destChainId, err := strconv.ParseUint(argDestChainId, 10, 16) if err != nil { return err } @@ -992,7 +992,7 @@ func CmdMirrorObject() *cobra.Command { if argDestChainId == "" { return fmt.Errorf("destination chain id should be provided") } - destChainId, err := strconv.ParseUint(argDestChainId, 10, 64) + destChainId, err := strconv.ParseUint(argDestChainId, 10, 16) if err != nil { return err } @@ -1053,7 +1053,7 @@ func CmdMirrorGroup() *cobra.Command { if argDestChainId == "" { return fmt.Errorf("destination chain id should be provided") } - destChainId, err := strconv.ParseUint(argDestChainId, 10, 64) + destChainId, err := strconv.ParseUint(argDestChainId, 10, 16) if err != nil { return err }