Skip to content

Commit

Permalink
Merge pull request #601 from yutianwu/fix_force_delete
Browse files Browse the repository at this point in the history
fix: fix uncharge issue when force-deleting objects
  • Loading branch information
yutianwu authored Apr 2, 2024
2 parents 866df5f + bdd78c2 commit 6868d14
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 24 deletions.
19 changes: 18 additions & 1 deletion app/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig.
app.registerUralUpgradeHandler()
app.registerPawneeUpgradeHandler()
app.registerSerengetiUpgradeHandler()
app.registerErdosUpgradeHandler()
// app.register...()
// ...
return nil
Expand Down Expand Up @@ -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)
})

Expand All @@ -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
})
}
1 change: 1 addition & 0 deletions deployment/localup/localup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
230 changes: 229 additions & 1 deletion e2e/tests/storage_rate_limit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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
}
23 changes: 23 additions & 0 deletions e2e/tests/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
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.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=
Expand Down
2 changes: 1 addition & 1 deletion x/storage/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Loading

0 comments on commit 6868d14

Please sign in to comment.