diff --git a/app/upgrade.go b/app/upgrade.go index 7d4e34531..c83d0ba79 100644 --- a/app/upgrade.go +++ b/app/upgrade.go @@ -31,6 +31,7 @@ func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig. app.registerUralUpgradeHandler() app.registerPawneeUpgradeHandler() app.registerSerengetiUpgradeHandler() + app.registerErdosUpgradeHandler() // app.register...() // ... return nil @@ -227,7 +228,6 @@ func (app *App) registerSerengetiUpgradeHandler() { app.GashubKeeper.SetMsgGasParams(ctx, *gashubtypes.NewMsgGasParamsWithFixedGas(sdk.MsgTypeURL(&storagemoduletypes.MsgDelegateCreateObject{}), 1.2e3)) app.GashubKeeper.SetMsgGasParams(ctx, *gashubtypes.NewMsgGasParamsWithFixedGas(sdk.MsgTypeURL(&storagemoduletypes.MsgDelegateUpdateObjectContent{}), 1.2e3)) app.GashubKeeper.SetMsgGasParams(ctx, *gashubtypes.NewMsgGasParamsWithFixedGas(sdk.MsgTypeURL(&storagemoduletypes.MsgSealObjectV2{}), 1.2e2)) - app.GashubKeeper.SetMsgGasParams(ctx, *gashubtypes.NewMsgGasParamsWithFixedGas(sdk.MsgTypeURL(&storagemoduletypes.MsgSetBucketFlowRateLimit{}), 1.2e3)) return app.mm.RunMigrations(ctx, app.configurator, fromVM) }) @@ -238,3 +238,20 @@ func (app *App) registerSerengetiUpgradeHandler() { return nil }) } + +func (app *App) registerErdosUpgradeHandler() { + // Register the upgrade handler + app.UpgradeKeeper.SetUpgradeHandler(upgradetypes.Erdos, + func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + app.Logger().Info("upgrade to ", plan.Name) + app.GashubKeeper.SetMsgGasParams(ctx, *gashubtypes.NewMsgGasParamsWithFixedGas(sdk.MsgTypeURL(&storagemoduletypes.MsgSetBucketFlowRateLimit{}), 1.2e3)) + return app.mm.RunMigrations(ctx, app.configurator, fromVM) + }) + + // Register the upgrade initializer + app.UpgradeKeeper.SetUpgradeInitializer(upgradetypes.Erdos, + func() error { + app.Logger().Info("Init Erdos upgrade") + return nil + }) +} diff --git a/deployment/localup/localup.sh b/deployment/localup/localup.sh index 5553b9ea1..bbdc9d9bd 100644 --- a/deployment/localup/localup.sh +++ b/deployment/localup/localup.sh @@ -179,6 +179,7 @@ function generate_genesis() { echo -e '[[upgrade]]\nname = "Ural"\nheight = 22\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml echo -e '[[upgrade]]\nname = "Pawnee"\nheight = 23\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml echo -e '[[upgrade]]\nname = "Serengeti"\nheight = 24\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml + echo -e '[[upgrade]]\nname = "Erdos"\nheight = 25\ninfo = ""' >> ${workspace}/.local/validator${i}/config/app.toml done # enable swagger API for validator0 diff --git a/e2e/tests/storage_rate_limit_test.go b/e2e/tests/storage_rate_limit_test.go index e2e01bd8d..b8468ef02 100644 --- a/e2e/tests/storage_rate_limit_test.go +++ b/e2e/tests/storage_rate_limit_test.go @@ -5,14 +5,85 @@ import ( "context" "fmt" "math" + "strconv" + "time" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + gashubtypes "github.com/cosmos/cosmos-sdk/x/gashub/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + "github.com/prysmaticlabs/prysm/crypto/bls" + + "github.com/bnb-chain/greenfield/e2e/core" + "github.com/bnb-chain/greenfield/sdk/keys" + types2 "github.com/bnb-chain/greenfield/sdk/types" storageutils "github.com/bnb-chain/greenfield/testutil/storage" storagetypes "github.com/bnb-chain/greenfield/x/storage/types" + virtualgrouptypes "github.com/bnb-chain/greenfield/x/virtualgroup/types" ) +func (s *StorageTestSuite) enableMessage() { + msgSetBucketFlowRateLimit := sdk.MsgTypeURL(&storagetypes.MsgSetBucketFlowRateLimit{}) + msgMigrateBuketGasParams := gashubtypes.NewMsgGasParamsWithFixedGas(msgSetBucketFlowRateLimit, 1.2e3) + + msgUpdateGasParams := gashubtypes.NewMsgSetMsgGasParams(authtypes.NewModuleAddress(govtypes.ModuleName).String(), []*gashubtypes.MsgGasParams{msgMigrateBuketGasParams}, nil) + + var err error + validator := s.Validator.GetAddr() + + ctx := context.Background() + + msgProposal, err := govtypesv1.NewMsgSubmitProposal( + []sdk.Msg{msgUpdateGasParams}, + sdk.Coins{sdk.NewCoin(s.BaseSuite.Config.Denom, types2.NewIntFromInt64WithDecimal(100, types2.DecimalBNB))}, + validator.String(), + "test", "test", "test", + ) + s.Require().NoError(err) + + txRes := s.SendTxBlock(s.Validator, msgProposal) + s.Require().Equal(txRes.Code, uint32(0)) + + // 3. query proposal and get proposal ID + var proposalId uint64 + for _, event := range txRes.Logs[0].Events { + if event.Type == "submit_proposal" { + for _, attr := range event.Attributes { + if attr.Key == "proposal_id" { + proposalId, err = strconv.ParseUint(attr.Value, 10, 0) + s.Require().NoError(err) + break + } + } + break + } + } + s.Require().True(proposalId != 0) + + queryProposal := &govtypesv1.QueryProposalRequest{ProposalId: proposalId} + _, err = s.Client.GovQueryClientV1.Proposal(ctx, queryProposal) + s.Require().NoError(err) + + // 4. submit MsgVote and wait the proposal exec + msgVote := govtypesv1.NewMsgVote(validator, proposalId, govtypesv1.OptionYes, "test") + txRes = s.SendTxBlock(s.Validator, msgVote) + s.Require().Equal(txRes.Code, uint32(0)) + + queryVoteParamsReq := govtypesv1.QueryParamsRequest{ParamsType: "voting"} + queryVoteParamsResp, err := s.Client.GovQueryClientV1.Params(ctx, &queryVoteParamsReq) + s.Require().NoError(err) + + // 5. wait a voting period and confirm that the proposal success. + s.T().Logf("voting period %s", *queryVoteParamsResp.Params.VotingPeriod) + time.Sleep(*queryVoteParamsResp.Params.VotingPeriod) + time.Sleep(1 * time.Second) + proposalRes, err := s.Client.GovQueryClientV1.Proposal(ctx, queryProposal) + s.Require().NoError(err) + s.Require().Equal(proposalRes.Proposal.Status, govtypesv1.ProposalStatus_PROPOSAL_STATUS_PASSED) +} + func (s *StorageTestSuite) TestSetBucketRateLimitToZero() { var err error sp := s.BaseSuite.PickStorageProvider() @@ -93,6 +164,8 @@ func (s *StorageTestSuite) TestSetBucketRateLimitToZero() { // 6. the payment account set the rate limit to a positive number // 7. user create an object in the bucket and it should pass func (s *StorageTestSuite) TestNotOwnerSetBucketRateLimit_Object() { + s.enableMessage() + var err error sp := s.BaseSuite.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() @@ -404,3 +477,158 @@ func (s *StorageTestSuite) TestQueryBucketRateLimit() { s.Require().Equal(queryBucketRateLimitResponse.IsSet, true) s.Require().Equal(queryBucketRateLimitResponse.FlowRateLimit, sdkmath.NewInt(100000000000000)) } + +func (s *StorageTestSuite) TestSetBucketFlowRateLimit_Discontinue() { + sp, user, bucketName, _, _, _ := s.createObjectWithNewGvg(storagetypes.VISIBILITY_TYPE_PRIVATE) + + // SetBucketRateLimit + msgSetBucketRateLimit := storagetypes.NewMsgSetBucketFlowRateLimit(user.GetAddr(), user.GetAddr(), user.GetAddr(), bucketName, sdkmath.NewInt(0)) + s.SendTxBlock(user, msgSetBucketRateLimit) + + queryHeadBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + queryHeadBucketResponse, err := s.Client.HeadBucket(context.Background(), &queryHeadBucketRequest) + s.Require().NoError(err) + + s.Require().Equal(queryHeadBucketResponse.ExtraInfo.IsRateLimited, true) + + msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") + txRes1 := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) + deleteAt1 := filterDiscontinueBucketEventFromTx(txRes1).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, deleteAt1) + + if blockTime >= deleteAt1 { + break + } + } +} + +func (s *StorageTestSuite) createObjectWithNewGvg(v storagetypes.VisibilityType) (*core.StorageProvider, keys.KeyManager, string, storagetypes.Uint, string, storagetypes.Uint) { + var err error + // CreateBucket + sp := s.BaseSuite.PickStorageProvider() + + _, secondarySps := s.GetSecondarySP(sp) + gvgID, _ := s.BaseSuite.CreateGlobalVirtualGroup(sp, 0, secondarySps, 1) + gvgResp, err := s.Client.VirtualGroupQueryClient.GlobalVirtualGroup(context.Background(), &virtualgrouptypes.QueryGlobalVirtualGroupRequest{ + GlobalVirtualGroupId: gvgID, + }) + s.Require().NoError(err) + gvg := gvgResp.GlobalVirtualGroup + + user := s.GenAndChargeAccounts(1, 1000000)[0] + bucketName := storageutils.GenRandomBucketName() + msgCreateBucket := storagetypes.NewMsgCreateBucket( + user.GetAddr(), bucketName, v, sp.OperatorKey.GetAddr(), + nil, math.MaxUint, nil, 0) + msgCreateBucket.PrimarySpApproval.GlobalVirtualGroupFamilyId = gvg.FamilyId + msgCreateBucket.PrimarySpApproval.Sig, err = sp.ApprovalKey.Sign(msgCreateBucket.GetApprovalBytes()) + s.Require().NoError(err) + s.SendTxBlock(user, msgCreateBucket) + + // HeadBucket + ctx := context.Background() + queryHeadBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + queryHeadBucketResponse, err := s.Client.HeadBucket(ctx, &queryHeadBucketRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.BucketName, bucketName) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.Owner, user.GetAddr().String()) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.GlobalVirtualGroupFamilyId, gvg.FamilyId) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.PaymentAddress, user.GetAddr().String()) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.Visibility, v) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.SourceType, storagetypes.SOURCE_TYPE_ORIGIN) + + // CreateObject + objectName := storageutils.GenRandomObjectName() + // create test buffer + var buffer bytes.Buffer + line := `1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,123` + // Create 1MiB content where each line contains 1024 characters. + for i := 0; i < 1024; i++ { + buffer.WriteString(fmt.Sprintf("[%05d] %s\n", i, line)) + } + payloadSize := buffer.Len() + checksum := sdk.Keccak256(buffer.Bytes()) + expectChecksum := [][]byte{checksum, checksum, checksum, checksum, checksum, checksum, checksum} + contextType := "text/event-stream" + msgCreateObject := storagetypes.NewMsgCreateObject(user.GetAddr(), bucketName, objectName, uint64(payloadSize), v, expectChecksum, contextType, storagetypes.REDUNDANCY_EC_TYPE, math.MaxUint, nil) + msgCreateObject.PrimarySpApproval.Sig, err = sp.ApprovalKey.Sign(msgCreateObject.GetApprovalBytes()) + s.Require().NoError(err) + s.SendTxBlock(user, msgCreateObject) + + // HeadObject + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectName, objectName) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.BucketName, bucketName) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.PayloadSize, uint64(payloadSize)) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.Visibility, v) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_CREATED) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.Owner, user.GetAddr().String()) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.Checksums, expectChecksum) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.SourceType, storagetypes.SOURCE_TYPE_ORIGIN) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.RedundancyType, storagetypes.REDUNDANCY_EC_TYPE) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ContentType, contextType) + + // SealObject + gvgId := gvg.Id + msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvgId, nil) + + secondarySigs := make([][]byte, 0) + secondarySPBlsPubKeys := make([]bls.PublicKey, 0) + blsSignHash := storagetypes.NewSecondarySpSealObjectSignDoc(s.GetChainID(), gvgId, queryHeadObjectResponse.ObjectInfo.Id, storagetypes.GenerateHash(queryHeadObjectResponse.ObjectInfo.Checksums[:])).GetBlsSignHash() + // every secondary sp signs the checksums + for _, spID := range gvg.SecondarySpIds { + sig, err := core.BlsSignAndVerify(s.StorageProviders[spID], blsSignHash) + s.Require().NoError(err) + secondarySigs = append(secondarySigs, sig) + pk, err := bls.PublicKeyFromBytes(s.StorageProviders[spID].BlsKey.PubKey().Bytes()) + s.Require().NoError(err) + secondarySPBlsPubKeys = append(secondarySPBlsPubKeys, pk) + } + aggBlsSig, err := core.BlsAggregateAndVerify(secondarySPBlsPubKeys, blsSignHash, secondarySigs) + s.Require().NoError(err) + msgSealObject.SecondarySpBlsAggSignatures = aggBlsSig + + s.T().Logf("msg %s", msgSealObject.String()) + s.SendTxBlock(sp.SealKey, msgSealObject) + + // ListBuckets + queryListBucketsRequest := storagetypes.QueryListBucketsRequest{} + queryListBucketResponse, err := s.Client.ListBuckets(ctx, &queryListBucketsRequest) + s.Require().NoError(err) + s.Require().Greater(len(queryListBucketResponse.BucketInfos), 0) + + // ListObject + queryListObjectsRequest := storagetypes.QueryListObjectsRequest{ + BucketName: bucketName, + } + queryListObjectsResponse, err := s.Client.ListObjects(ctx, &queryListObjectsRequest) + s.Require().NoError(err) + s.Require().Equal(len(queryListObjectsResponse.ObjectInfos), 1) + s.Require().Equal(queryListObjectsResponse.ObjectInfos[0].ObjectName, objectName) + return sp, user, bucketName, queryHeadBucketResponse.BucketInfo.Id, objectName, queryListObjectsResponse.ObjectInfos[0].Id +} diff --git a/e2e/tests/storage_test.go b/e2e/tests/storage_test.go index 63ee84549..edf571650 100644 --- a/e2e/tests/storage_test.go +++ b/e2e/tests/storage_test.go @@ -985,6 +985,29 @@ func (s *StorageTestSuite) TestDiscontinueBucket_UserDeleted() { s.Require().True(statusRes.SyncInfo.LatestBlockHeight > heightAfter) } +func (s *StorageTestSuite) GetSecondarySP(sps ...*core.StorageProvider) ([]*core.StorageProvider, []uint32) { + var secondarySPs []*core.StorageProvider + var secondarySPIDs []uint32 + + for _, ssp := range s.StorageProviders { + isSecondSP := true + for _, sp := range sps { + if ssp.Info.Id == sp.Info.Id { + isSecondSP = false + break + } + } + if isSecondSP { + secondarySPIDs = append(secondarySPIDs, ssp.Info.Id) + secondarySPs = append(secondarySPs, ssp) + } + if len(secondarySPIDs) == 6 { + break + } + } + return secondarySPs, secondarySPIDs +} + // createObject with default VISIBILITY_TYPE_PRIVATE func (s *StorageTestSuite) createObject() (*core.StorageProvider, keys.KeyManager, string, storagetypes.Uint, string, storagetypes.Uint) { return s.createObjectWithVisibility(storagetypes.VISIBILITY_TYPE_PRIVATE) diff --git a/go.mod b/go.mod index ffdc5452e..5f01237ad 100644 --- a/go.mod +++ b/go.mod @@ -179,7 +179,7 @@ replace ( github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-cometbft v1.2.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.5.1-0.20240314024318-a972393c0430 + github.com/cosmos/cosmos-sdk => github.com/bnb-chain/greenfield-cosmos-sdk v1.5.1-0.20240402031746-d46857cfafc0 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 diff --git a/go.sum b/go.sum index 74f8c9031..aceab18b2 100644 --- a/go.sum +++ b/go.sum @@ -163,8 +163,8 @@ github.com/bnb-chain/greenfield-cometbft v1.2.0 h1:LTStppZS9WkVj0TfEYKkk5OAQDGfY github.com/bnb-chain/greenfield-cometbft v1.2.0/go.mod h1:WVOEZ59UYM2XePQH47/IQfcInspDn8wbRXhFSJrbU1c= 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.5.1-0.20240314024318-a972393c0430 h1:Lerm4iJITbmJBOqRj/IPQhS8cvjTKOfuq3XOoDgjAtM= -github.com/bnb-chain/greenfield-cosmos-sdk v1.5.1-0.20240314024318-a972393c0430/go.mod h1:XF8U3VN1euzLkIR5xiSNyQSnBabvnD86oz6fgdrpteQ= +github.com/bnb-chain/greenfield-cosmos-sdk v1.5.1-0.20240402031746-d46857cfafc0 h1:Cm9EWuktgeyYotoL6ef0XpqB2ECjIzDwQxqFmgfPjTM= +github.com/bnb-chain/greenfield-cosmos-sdk v1.5.1-0.20240402031746-d46857cfafc0/go.mod h1:XF8U3VN1euzLkIR5xiSNyQSnBabvnD86oz6fgdrpteQ= 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/x/storage/keeper/keeper.go b/x/storage/keeper/keeper.go index 3225a521c..3b30ff330 100644 --- a/x/storage/keeper/keeper.go +++ b/x/storage/keeper/keeper.go @@ -270,7 +270,7 @@ func (k Keeper) doDeleteBucket(ctx sdk.Context, operator sdk.AccAddress, bucketI } } - if ctx.IsUpgraded(upgradetypes.Serengeti) { + if ctx.IsUpgraded(upgradetypes.Erdos) { // delete bucket flow rate limit status k.deleteBucketFlowRateLimitStatus(ctx, bucketInfo.BucketName, bucketInfo.Id) } diff --git a/x/storage/keeper/payment.go b/x/storage/keeper/payment.go index 37c044895..462359a3f 100644 --- a/x/storage/keeper/payment.go +++ b/x/storage/keeper/payment.go @@ -25,7 +25,7 @@ func (k Keeper) ChargeBucketReadFee(ctx sdk.Context, bucketInfo *storagetypes.Bu return fmt.Errorf("charge bucket read fee failed, get bucket bill failed: %s %s", bucketInfo.BucketName, err.Error()) } - if ctx.IsUpgraded(upgradetypes.Serengeti) { + if ctx.IsUpgraded(upgradetypes.Erdos) { err := k.isBucketFlowRateUnderLimit(ctx, sdk.MustAccAddressFromHex(bucketInfo.PaymentAddress), sdk.MustAccAddressFromHex(bucketInfo.Owner), bucketInfo.BucketName, bill) if err != nil { return err @@ -46,7 +46,7 @@ func (k Keeper) UnChargeBucketReadFee(ctx sdk.Context, bucketInfo *storagetypes. return fmt.Errorf("unexpected total store charge size: %s, %d", bucketInfo.BucketName, internalBucketInfo.TotalChargeSize) } - if ctx.IsUpgraded(upgradetypes.Serengeti) { + if ctx.IsUpgraded(upgradetypes.Erdos) { // if the bucket's flow rate limit is set to zero, no need to uncharge, since the bucket is already uncharged if k.IsBucketRateLimited(ctx, bucketInfo.BucketName) { return nil @@ -145,7 +145,7 @@ func (k Keeper) lockObjectStoreFee(ctx sdk.Context, bucketInfo *storagetypes.Buc }) } - if ctx.IsUpgraded(upgradetypes.Serengeti) && k.shouldCheckRateLimit(ctx, paymentAddr, sdk.MustAccAddressFromHex(bucketInfo.Owner), bucketInfo.BucketName) { + if ctx.IsUpgraded(upgradetypes.Erdos) && k.shouldCheckRateLimit(ctx, paymentAddr, sdk.MustAccAddressFromHex(bucketInfo.Owner), bucketInfo.BucketName) { internalBucketInfo := k.MustGetInternalBucketInfo(ctx, bucketInfo.Id) internalBucketInfo.PriceTime = timestamp nextBill, err := k.GetBucketReadStoreBill(ctx, bucketInfo, internalBucketInfo) @@ -346,7 +346,7 @@ func (k Keeper) ChargeViaBucketChange(ctx sdk.Context, bucketInfo *storagetypes. return fmt.Errorf("get new bucket bill failed: %s %w", bucketInfo.BucketName, err) } - if ctx.IsUpgraded(upgradetypes.Serengeti) { + if ctx.IsUpgraded(upgradetypes.Erdos) { isPreviousBucketLimited := k.IsBucketRateLimited(ctx, bucketInfo.BucketName) if prevPaymentAccount == bucketInfo.PaymentAddress && isPreviousBucketLimited { @@ -434,24 +434,46 @@ func (k Keeper) ChargeViaObjectChange(ctx sdk.Context, bucketInfo *storagetypes. userFlows.Flows = append(userFlows.Flows, getNegFlows(preOutFlows)...) userFlows.Flows = append(userFlows.Flows, newOutFlows...) - if ctx.IsUpgraded(upgradetypes.Serengeti) { - currentBill, err := k.GetBucketReadStoreBill(ctx, bucketInfo, internalBucketInfo) - if err != nil { - return nil, fmt.Errorf("get bucket bill failed: %s %w", bucketInfo.BucketName, err) + if ctx.IsUpgraded(upgradetypes.Erdos) { + var shouldApplyFlowRate = true + forced, _ := ctx.Value(types.ForceUpdateStreamRecordKey).(bool) + if forced { + isRateLimited := k.IsBucketRateLimited(ctx, bucketInfo.BucketName) + if isRateLimited { + // if the bucket is rate limited, no need to apply the flow rate since + // the bucket is already uncharged + shouldApplyFlowRate = false + } + } else { + // we should only check the flow rate limit when is not forced + currentBill, err := k.GetBucketReadStoreBill(ctx, bucketInfo, internalBucketInfo) + if err != nil { + return nil, fmt.Errorf("get bucket bill failed: %s %w", bucketInfo.BucketName, err) + } + + err = k.isBucketFlowRateUnderLimit(ctx, sdk.MustAccAddressFromHex(bucketInfo.PaymentAddress), sdk.MustAccAddressFromHex(bucketInfo.Owner), bucketInfo.BucketName, currentBill) + if err != nil { + return nil, err + } } - err = k.isBucketFlowRateUnderLimit(ctx, sdk.MustAccAddressFromHex(bucketInfo.PaymentAddress), sdk.MustAccAddressFromHex(bucketInfo.Owner), bucketInfo.BucketName, currentBill) + if shouldApplyFlowRate { + err = k.paymentKeeper.ApplyUserFlowsList(ctx, []types.UserFlows{userFlows}) + if err != nil { + ctx.Logger().Error("charge object store fee failed", "bucket", bucketInfo.BucketName, + "object", objectInfo.ObjectName, "err", err.Error()) + return nil, err + } + } + } else { + err = k.paymentKeeper.ApplyUserFlowsList(ctx, []types.UserFlows{userFlows}) if err != nil { + ctx.Logger().Error("charge object store fee failed", "bucket", bucketInfo.BucketName, + "object", objectInfo.ObjectName, "err", err.Error()) return nil, err } } - err = k.paymentKeeper.ApplyUserFlowsList(ctx, []types.UserFlows{userFlows}) - if err != nil { - ctx.Logger().Error("charge object store fee failed", "bucket", bucketInfo.BucketName, - "object", objectInfo.ObjectName, "err", err.Error()) - return nil, err - } // merge outflows for early deletion usage return k.paymentKeeper.MergeOutFlows(userFlows.Flows), nil } @@ -548,7 +570,7 @@ func (k Keeper) GetBucketReadStoreBill(ctx sdk.Context, bucketInfo *storagetypes func (k Keeper) UnChargeBucketReadStoreFee(ctx sdk.Context, bucketInfo *storagetypes.BucketInfo, internalBucketInfo *storagetypes.InternalBucketInfo) error { - if ctx.IsUpgraded(upgradetypes.Serengeti) { + if ctx.IsUpgraded(upgradetypes.Erdos) { // if the bucket's flow rate limit is set to zero, no need to uncharge, since the bucket is already uncharged if k.IsBucketRateLimited(ctx, bucketInfo.BucketName) { return nil @@ -575,7 +597,7 @@ func (k Keeper) ChargeBucketReadStoreFee(ctx sdk.Context, bucketInfo *storagetyp return fmt.Errorf("get bucket bill failed: %s %s", bucketInfo.BucketName, err.Error()) } - if ctx.IsUpgraded(upgradetypes.Serengeti) { + if ctx.IsUpgraded(upgradetypes.Erdos) { err := k.isBucketFlowRateUnderLimit(ctx, sdk.MustAccAddressFromHex(bucketInfo.PaymentAddress), sdk.MustAccAddressFromHex(bucketInfo.Owner), bucketInfo.BucketName, bill) if err != nil { return err diff --git a/x/storage/keeper/verify.go b/x/storage/keeper/verify.go index 36f5072ee..2b4dd7001 100644 --- a/x/storage/keeper/verify.go +++ b/x/storage/keeper/verify.go @@ -16,7 +16,7 @@ func (k Keeper) VerifyPaymentAccount(ctx sdk.Context, paymentAddress string, own } // don't check if the payment account is owned by the owner account - if !ctx.IsUpgraded(upgradetypes.Serengeti) { + if !ctx.IsUpgraded(upgradetypes.Erdos) { if !k.paymentKeeper.IsPaymentAccountOwner(ctx, paymentAcc, ownerAcc) { return nil, paymenttypes.ErrNotPaymentAccountOwner }