Skip to content

Commit

Permalink
fix: fail to resume frozen payment account when netflow is zero
Browse files Browse the repository at this point in the history
  • Loading branch information
forcodedancing committed Nov 6, 2024
1 parent e490ec7 commit fb45cbf
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 4 deletions.
17 changes: 17 additions & 0 deletions app/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig.
app.registerVeldUpgradeHandler()
app.registerMongolianUpgradeHandler()
app.registerAltaiUpgradeHandler()
app.registerSavannaUpgradeHandler()
// app.register...()
// ...
return nil
Expand Down Expand Up @@ -313,3 +314,19 @@ func (app *App) registerAltaiUpgradeHandler() {
return nil
})
}

func (app *App) registerSavannaUpgradeHandler() {
// Register the upgrade handler
app.UpgradeKeeper.SetUpgradeHandler(upgradetypes.Savanna,
func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
app.Logger().Info("upgrade to ", plan.Name)
return app.mm.RunMigrations(ctx, app.configurator, fromVM)
})

// Register the upgrade initializer
app.UpgradeKeeper.SetUpgradeInitializer(upgradetypes.Savanna,
func() error {
app.Logger().Info("Init Savanna upgrade")
return nil
})
}
1 change: 1 addition & 0 deletions deployment/localup/localup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ function generate_genesis() {
echo -e '[[upgrade]]\nname = "Erdos"\nheight = 25\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml
echo -e '[[upgrade]]\nname = "Veld"\nheight = 26\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml
echo -e '[[upgrade]]\nname = "Mongolian"\nheight = 27\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml
echo -e '[[upgrade]]\nname = "Savanna"\nheight = 28\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml
done

# enable swagger API for validator0
Expand Down
128 changes: 128 additions & 0 deletions e2e/tests/payment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2170,6 +2170,134 @@ func (s *PaymentTestSuite) TestDiscontinue_MultiBuckets() {
s.Require().True(streamRecordsAfter.User.LockBalance.IsZero())
}

func (s *PaymentTestSuite) TestDeposit_FrozenAccount_NetflowIsZero() {
defer s.revertParams()

ctx := context.Background()
sp := s.PickStorageProvider()
gvg, found := sp.GetFirstGlobalVirtualGroup()
s.Require().True(found)
queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{
FamilyId: gvg.FamilyId,
})
s.Require().NoError(err)
family := queryFamilyResponse.GlobalVirtualGroupFamily
user := s.GenAndChargeAccounts(1, 1000000)[0]

streamAddresses := []string{
user.GetAddr().String(),
family.VirtualPaymentAddress,
gvg.VirtualPaymentAddress,
paymenttypes.ValidatorTaxPoolAddress.String(),
}

// update params
params := s.queryParams()
params.VersionedParams.ReserveTime = 8
params.ForcedSettleTime = 5
s.updateParams(params)

// create bucket
bucketName := s.createBucket(sp, gvg, user, 0)

// create & seal objects
for i := 0; i < 2; i++ {
_, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false)
s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1)
queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{
BucketName: bucketName,
ObjectName: objectName1,
}
queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest)
s.Require().NoError(err)
s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED)
time.Sleep(200 * time.Millisecond)
}

// transfer out all balance
queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()}
queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest)
s.Require().NoError(err)

msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins(
sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)),
))

simulateResponse := s.SimulateTx(msgSend, user)
gasLimit := simulateResponse.GasInfo.GetGasUsed()
gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice())
s.Require().NoError(err)

msgSend.Amount = sdk.NewCoins(
sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))))),
)
s.SendTxBlock(user, msgSend)
queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest)
s.Require().NoError(err)
s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64())

// wait account to be frozen
time.Sleep(8 * time.Second)
streamRecord := s.getStreamRecord(user.GetAddr().String())
s.Require().True(streamRecord.Status == paymenttypes.STREAM_ACCOUNT_STATUS_FROZEN)
s.Require().True(streamRecord.NetflowRate.IsZero())
s.Require().True(streamRecord.FrozenNetflowRate.IsNegative())

// force delete bucket
msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test")
txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket)
deleteAt := filterDiscontinueBucketEventFromTx(txRes).DeleteAt

for {
time.Sleep(200 * time.Millisecond)
statusRes, err := s.TmClient.TmClient.Status(context.Background())
s.Require().NoError(err)
blockTime := statusRes.SyncInfo.LatestBlockTime.Unix()

s.T().Logf("current blockTime: %d, delete blockTime: %d", blockTime, deleteAt)

if blockTime > deleteAt {
break
}
}

_, err = s.Client.HeadBucket(ctx, &storagetypes.QueryHeadBucketRequest{BucketName: bucketName})
s.Require().ErrorContains(err, "No such bucket")
streamRecordsAfter := s.getStreamRecords(streamAddresses)
s.Require().True(streamRecordsAfter.User.NetflowRate.IsZero())
s.Require().True(streamRecordsAfter.User.FrozenNetflowRate.IsZero())
s.Require().True(streamRecordsAfter.User.LockBalance.IsZero())
s.Require().True(streamRecordsAfter.User.StaticBalance.IsZero())
s.Require().True(streamRecordsAfter.User.BufferBalance.IsZero())

// deposit payment account
helper := s.GenAndChargeAccounts(1, 1000000)[0]
msgSend = banktypes.NewMsgSend(helper.GetAddr(), user.GetAddr(), sdk.NewCoins(
sdk.NewCoin(s.Config.Denom, sdk.NewInt(2e18)),
))
s.SendTxBlock(helper, msgSend)
_, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest)
s.Require().NoError(err)

msgDeposit := &paymenttypes.MsgDeposit{
Creator: user.GetAddr().String(),
To: user.GetAddr().String(),
Amount: sdk.NewInt(1e18),
}
_ = s.SendTxBlock(user, msgDeposit)
streamRecordsAfter = s.getStreamRecords(streamAddresses)
s.Require().True(streamRecordsAfter.User.Status == paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE)
s.Require().True(streamRecordsAfter.User.StaticBalance.Equal(sdk.NewInt(1e18)))
s.Require().True(streamRecordsAfter.User.SettleTimestamp == 0)

// create bucket with quota again
_ = s.createBucket(sp, gvg, user, 100)
streamRecordsAfter = s.getStreamRecords(streamAddresses)
s.Require().True(streamRecordsAfter.User.StaticBalance.LT(sdk.NewInt(1e18)))
s.Require().True(streamRecordsAfter.User.BufferBalance.GT(sdk.NewInt(0)))
s.Require().True(streamRecordsAfter.User.SettleTimestamp > 0)
}

func TestPaymentTestSuite(t *testing.T) {
suite.Run(t, new(PaymentTestSuite))
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ replace (
github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-cometbft v1.3.0
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 v1.9.2
github.com/cosmos/cosmos-sdk => github.com/bnb-chain/greenfield-cosmos-sdk v1.9.3-0.20241106114330-708c5e70e9f3
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
github.com/wercker/journalhook => github.com/wercker/journalhook v0.0.0-20230927020745-64542ffa4117
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ github.com/bnb-chain/greenfield-cometbft v1.3.0 h1:v3nZ16ledTZGF5Csys7fTQGZcEV78
github.com/bnb-chain/greenfield-cometbft v1.3.0/go.mod h1:0D+VPivZTeBldjtGGi9LKbBnKEO/RtMRJikie92LkYI=
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 v1.9.2 h1:hqZ4v4M3nkBNs1dXbAQkMBrNQuP9maQOSU+rBwzAemQ=
github.com/bnb-chain/greenfield-cosmos-sdk v1.9.2/go.mod h1:2bwmwdXYBISnQoMwgAcZTVGt21lMsHZSeeeMByTvDlQ=
github.com/bnb-chain/greenfield-cosmos-sdk v1.9.3-0.20241106114330-708c5e70e9f3 h1:76nYX3W9tcS4tGhk3kvVAkosQfDoaYiZZu5sKXY3nz0=
github.com/bnb-chain/greenfield-cosmos-sdk v1.9.3-0.20241106114330-708c5e70e9f3/go.mod h1:2bwmwdXYBISnQoMwgAcZTVGt21lMsHZSeeeMByTvDlQ=
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=
Expand Down
11 changes: 10 additions & 1 deletion x/payment/keeper/stream_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,16 +380,25 @@ func (k Keeper) TryResumeStreamRecord(ctx sdk.Context, streamRecord *types.Strea
reserveTime := params.VersionedParams.ReserveTime
forcedSettleTime := params.ForcedSettleTime

now := ctx.BlockTime().Unix()
totalRate := streamRecord.NetflowRate.Add(streamRecord.FrozenNetflowRate)
streamRecord.StaticBalance = streamRecord.StaticBalance.Add(depositBalance)

if totalRate.IsZero() && ctx.IsUpgraded(upgradetypes.Savanna) {
streamRecord.Status = types.STREAM_ACCOUNT_STATUS_ACTIVE
streamRecord.CrudTimestamp = now
streamRecord.SettleTimestamp = 0
k.SetStreamRecord(ctx, streamRecord)
return nil
}

expectedBalanceToResume := totalRate.Neg().Mul(sdkmath.NewIntFromUint64(reserveTime))
if streamRecord.StaticBalance.LT(expectedBalanceToResume) {
// deposit balance is not enough to resume, only add static balance
k.SetStreamRecord(ctx, streamRecord)
return nil
}

now := ctx.BlockTime().Unix()
prevSettleTime := streamRecord.SettleTimestamp
streamRecord.SettleTimestamp = now + streamRecord.StaticBalance.Quo(totalRate.Abs()).Int64() - int64(forcedSettleTime)
streamRecord.BufferBalance = expectedBalanceToResume
Expand Down

0 comments on commit fb45cbf

Please sign in to comment.