Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix uncharge issue when force-deleting objects #601

Merged
merged 8 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 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,21 @@ 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.VirtualgroupKeeper.MigrateGlobalVirtualGroupFamiliesForSP(ctx)
yutianwu marked this conversation as resolved.
Show resolved Hide resolved
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
Loading