diff --git a/e2e/core/basesuite.go b/e2e/core/basesuite.go index bde8bab85..1aec2f931 100644 --- a/e2e/core/basesuite.go +++ b/e2e/core/basesuite.go @@ -128,7 +128,7 @@ func (s *BaseSuite) InitChain() { func (s *BaseSuite) SetupSuite() { s.Config = InitConfig() initValidatorOnce.Do(func() { - s.InitChain() + //s.InitChain() }) s.Client, _ = client.NewGreenfieldClient(s.Config.TendermintAddr, s.Config.ChainId) diff --git a/e2e/tests/storage_test.go b/e2e/tests/storage_test.go index 02dff6ec9..57f834162 100644 --- a/e2e/tests/storage_test.go +++ b/e2e/tests/storage_test.go @@ -11,6 +11,8 @@ import ( "testing" "time" + paymenttypes "github.com/bnb-chain/greenfield/x/payment/types" + sdkmath "cosmossdk.io/math" ctypes "github.com/cometbft/cometbft/rpc/core/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -2407,3 +2409,129 @@ func (s *StorageTestSuite) TestDeleteCreateObject_InCreatedStatus() { _, err = s.Client.HeadObject(ctx, &queryHeadObjectRequest) s.Require().EqualError(err, "rpc error: code = Unknown desc = No such object: unknown request") } + +func (s *StorageTestSuite) TestDisallowChangePaymentAccount() { + var err error + sp := s.BaseSuite.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + user := s.User + // CreateBucket + bucketName := storageutils.GenRandomBucketName() + msgCreateBucket := storagetypes.NewMsgCreateBucket( + user.GetAddr(), bucketName, storagetypes.VISIBILITY_TYPE_PUBLIC_READ, 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, + } + _, err = s.Client.HeadBucket(ctx, &queryHeadBucketRequest) + s.Require().NoError(err) + + // create a new payment account + msgCreatePaymentAccount := &paymenttypes.MsgCreatePaymentAccount{ + Creator: user.GetAddr().String(), + } + _ = s.SendTxBlock(user, msgCreatePaymentAccount) + // query user's payment accounts + queryGetPaymentAccountsByOwnerRequest := paymenttypes.QueryPaymentAccountsByOwnerRequest{ + Owner: user.GetAddr().String(), + } + paymentAccounts, err := s.Client.PaymentAccountsByOwner(ctx, &queryGetPaymentAccountsByOwnerRequest) + s.Require().NoError(err) + s.T().Log(paymentAccounts) + s.Require().Equal(1, len(paymentAccounts.PaymentAccounts)) + paymentAccountAddr := sdk.MustAccAddressFromHex(paymentAccounts.PaymentAccounts[0]) + + msgDeposit := &paymenttypes.MsgDeposit{ + Creator: user.GetAddr().String(), + To: paymentAccountAddr.String(), + Amount: types.NewIntFromInt64WithDecimal(2, types.DecimalBNB), + } + _ = s.SendTxBlock(user, msgDeposit) + + // UpdateBucketInfo is fine for no created object + msgUpdateBucketInfo := storagetypes.NewMsgUpdateBucketInfo( + user.GetAddr(), bucketName, nil, paymentAccountAddr, storagetypes.VISIBILITY_TYPE_PRIVATE) + s.Require().NoError(err) + s.SendTxBlock(user, msgUpdateBucketInfo) + s.Require().NoError(err) + + // 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), + storagetypes.VISIBILITY_TYPE_PRIVATE, 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) + + // UpdateBucketInfo is not fine for there is a created object + msgUpdateBucketInfo = storagetypes.NewMsgUpdateBucketInfo( + user.GetAddr(), bucketName, nil, user.GetAddr(), storagetypes.VISIBILITY_TYPE_PRIVATE) + s.Require().NoError(err) + s.SendTxBlockWithExpectErrorString(msgUpdateBucketInfo, user, "has unseald objects") + + // 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) + + // UpdateBucketInfo is fine for there is no created object + msgUpdateBucketInfo = storagetypes.NewMsgUpdateBucketInfo( + user.GetAddr(), bucketName, nil, user.GetAddr(), storagetypes.VISIBILITY_TYPE_PRIVATE) + s.Require().NoError(err) + s.SendTxBlock(user, msgUpdateBucketInfo) + s.Require().NoError(err) +} diff --git a/x/storage/keeper/keeper.go b/x/storage/keeper/keeper.go index c9a0f03d7..e8b802f9c 100644 --- a/x/storage/keeper/keeper.go +++ b/x/storage/keeper/keeper.go @@ -235,7 +235,7 @@ func (k Keeper) doDeleteBucket(ctx sdk.Context, operator sdk.AccAddress, bucketI store.Delete(types.GetQuotaKey(bucketInfo.Id)) store.Delete(types.GetInternalBucketInfoKey(bucketInfo.Id)) store.Delete(types.GetMigrationBucketKey(bucketInfo.Id)) - store.Delete(types.GetCreatedObjectCountKey(bucketInfo.Id)) + store.Delete(types.GetLockedObjectCountKey(bucketInfo.Id)) err := k.appendResourceIdForGarbageCollection(ctx, resource.RESOURCE_TYPE_BUCKET, bucketInfo.Id) if err != nil { @@ -336,7 +336,7 @@ func (k Keeper) ForceDeleteBucket(ctx sdk.Context, bucketId sdkmath.Uint, cap ui return false, deleted, err } if ctx.IsUpgraded(upgradetypes.Pawnee) { - k.DecreaseCreatedObjectCount(ctx, bucketInfo.Id) + k.DecreaseLockedObjectCount(ctx, bucketInfo.Id) } } else if objectStatus == types.OBJECT_STATUS_SEALED { internalBucketInfo := k.MustGetInternalBucketInfo(ctx, bucketInfo.Id) @@ -353,6 +353,7 @@ func (k Keeper) ForceDeleteBucket(ctx sdk.Context, bucketId sdkmath.Uint, cap ui if err != nil { return false, deleted, err } + k.DecreaseLockedObjectCount(ctx, bucketInfo.Id) } } if err := k.doDeleteObject(ctx, spOperatorAddr, bucketInfo, &objectInfo); err != nil { @@ -437,7 +438,7 @@ func (k Keeper) UpdateBucketInfo(ctx sdk.Context, operator sdk.AccAddress, bucke } if ctx.IsUpgraded(upgradetypes.Pawnee) { - if !paymentAcc.Equals(sdk.MustAccAddressFromHex(bucketInfo.PaymentAddress)) && k.GetCreatedObjectCount(ctx, bucketInfo.Id) != 0 { + if !paymentAcc.Equals(sdk.MustAccAddressFromHex(bucketInfo.PaymentAddress)) && k.GetLockedObjectCount(ctx, bucketInfo.Id) != 0 { return types.ErrUpdatePaymentAccountFailed.Wrapf("The bucket %s has unseald objects", bucketInfo.BucketName) } } @@ -662,7 +663,7 @@ func (k Keeper) CreateObject( store.Set(types.GetBucketByIDKey(bucketInfo.Id), bbz) if ctx.IsUpgraded(upgradetypes.Pawnee) { if objectInfo.ObjectStatus == types.OBJECT_STATUS_CREATED { - k.IncreaseCreatedObjectCount(ctx, bucketInfo.Id) + k.IncreaseLockedObjectCount(ctx, bucketInfo.Id) } } @@ -866,7 +867,7 @@ func (k Keeper) SealObject( bbz := k.cdc.MustMarshal(bucketInfo) store.Set(types.GetBucketByIDKey(bucketInfo.Id), bbz) if ctx.IsUpgraded(upgradetypes.Pawnee) { - k.DecreaseCreatedObjectCount(ctx, bucketInfo.Id) + k.DecreaseLockedObjectCount(ctx, bucketInfo.Id) } obz := k.cdc.MustMarshal(objectInfo) @@ -954,7 +955,7 @@ func (k Keeper) CancelCreateObject( store.Set(types.GetBucketByIDKey(bucketInfo.Id), bbz) if ctx.IsUpgraded(upgradetypes.Pawnee) { if objectInfo.ObjectStatus == types.OBJECT_STATUS_CREATED { - k.DecreaseCreatedObjectCount(ctx, bucketInfo.Id) + k.DecreaseLockedObjectCount(ctx, bucketInfo.Id) } } @@ -1009,6 +1010,7 @@ func (k Keeper) DeleteObject( if err != nil { return err } + k.DecreaseLockedObjectCount(ctx, bucketInfo.Id) } internalBucketInfo := k.MustGetInternalBucketInfo(ctx, bucketInfo.Id) @@ -1082,7 +1084,7 @@ func (k Keeper) ForceDeleteObject(ctx sdk.Context, objectId sdkmath.Uint) error return err } if ctx.IsUpgraded(upgradetypes.Pawnee) { - k.DecreaseCreatedObjectCount(ctx, bucketInfo.Id) + k.DecreaseLockedObjectCount(ctx, bucketInfo.Id) } } else if objectStatus == types.OBJECT_STATUS_SEALED { internalBucketInfo := k.MustGetInternalBucketInfo(ctx, bucketInfo.Id) @@ -1100,6 +1102,7 @@ func (k Keeper) ForceDeleteObject(ctx sdk.Context, objectId sdkmath.Uint) error if err != nil { return err } + k.DecreaseLockedObjectCount(ctx, bucketInfo.Id) } } @@ -1200,7 +1203,7 @@ func (k Keeper) CopyObject( store.Set(types.GetBucketByIDKey(dstBucketInfo.Id), bbz) if ctx.IsUpgraded(upgradetypes.Pawnee) { if objectInfo.ObjectStatus == types.OBJECT_STATUS_CREATED { - k.IncreaseCreatedObjectCount(ctx, dstBucketInfo.Id) + k.IncreaseLockedObjectCount(ctx, dstBucketInfo.Id) } } @@ -1269,6 +1272,11 @@ func (k Keeper) RejectSealObject(ctx sdk.Context, operator sdk.AccAddress, bucke store.Delete(types.GetObjectKey(bucketName, objectName)) store.Delete(types.GetObjectByIDKey(objectInfo.Id)) } + + if ctx.IsUpgraded(upgradetypes.Pawnee) { + k.DecreaseLockedObjectCount(ctx, bucketInfo.Id) + } + return ctx.EventManager().EmitTypedEvents(&types.EventRejectSealObject{ Operator: operator.String(), BucketName: bucketInfo.BucketName, @@ -2540,6 +2548,7 @@ func (k Keeper) UpdateObjectContent( if err != nil { return err } + k.IncreaseLockedObjectCount(ctx, bucketInfo.Id) } obz := k.cdc.MustMarshal(objectInfo) @@ -2598,6 +2607,7 @@ func (k Keeper) CancelUpdateObjectContent( objectInfo.IsUpdating = false obz := k.cdc.MustMarshal(objectInfo) store.Set(types.GetObjectByIDKey(objectInfo.Id), obz) + k.DecreaseLockedObjectCount(ctx, bucketInfo.Id) return ctx.EventManager().EmitTypedEvents(&types.EventCancelUpdateObjectContent{ Operator: operator.String(), @@ -2607,10 +2617,10 @@ func (k Keeper) CancelUpdateObjectContent( }) } -func (k Keeper) GetCreatedObjectCount(ctx sdk.Context, bucketId sdkmath.Uint) uint64 { +func (k Keeper) GetLockedObjectCount(ctx sdk.Context, bucketId sdkmath.Uint) uint64 { store := ctx.KVStore(k.storeKey) - key := types.GetCreatedObjectCountKey(bucketId) + key := types.GetLockedObjectCountKey(bucketId) bz := store.Get(key) current := uint64(0) if bz != nil { @@ -2619,10 +2629,10 @@ func (k Keeper) GetCreatedObjectCount(ctx sdk.Context, bucketId sdkmath.Uint) ui return current } -func (k Keeper) IncreaseCreatedObjectCount(ctx sdk.Context, bucketId sdkmath.Uint) { +func (k Keeper) IncreaseLockedObjectCount(ctx sdk.Context, bucketId sdkmath.Uint) { store := ctx.KVStore(k.storeKey) - key := types.GetCreatedObjectCountKey(bucketId) + key := types.GetLockedObjectCountKey(bucketId) bz := store.Get(key) before := uint64(0) if bz != nil { @@ -2635,10 +2645,10 @@ func (k Keeper) IncreaseCreatedObjectCount(ctx sdk.Context, bucketId sdkmath.Uin store.Set(key, bz) } -func (k Keeper) DecreaseCreatedObjectCount(ctx sdk.Context, bucketId sdkmath.Uint) { +func (k Keeper) DecreaseLockedObjectCount(ctx sdk.Context, bucketId sdkmath.Uint) { store := ctx.KVStore(k.storeKey) - key := types.GetCreatedObjectCountKey(bucketId) + key := types.GetLockedObjectCountKey(bucketId) bz := store.Get(key) before := uint64(0) if bz != nil { @@ -2657,8 +2667,3 @@ func (k Keeper) DecreaseCreatedObjectCount(ctx sdk.Context, bucketId sdkmath.Uin binary.BigEndian.PutUint64(bz, after) store.Set(key, bz) } - -func (k Keeper) DeleteCreatedObjectCount(ctx sdk.Context, bucketId sdkmath.Uint) { - store := ctx.KVStore(k.storeKey) - store.Delete(types.GetCreatedObjectCountKey(bucketId)) -} diff --git a/x/storage/types/keys.go b/x/storage/types/keys.go index d5e12bc17..49406a8ca 100644 --- a/x/storage/types/keys.go +++ b/x/storage/types/keys.go @@ -40,7 +40,7 @@ var ( ShadowObjectInfoPrefix = []byte{0x16} - CreatedObjectCountPrefix = []byte{0x17} + LockedObjectCountPrefix = []byte{0x17} // key to track count of created/updating objects, which will involve lock fee BucketByIDPrefix = []byte{0x21} ObjectByIDPrefix = []byte{0x22} @@ -168,7 +168,7 @@ func GetInternalBucketInfoKey(bucketID math.Uint) []byte { return append(InternalBucketInfoPrefix, seq.EncodeSequence(bucketID)...) } -func GetCreatedObjectCountKey(bucketId math.Uint) []byte { +func GetLockedObjectCountKey(bucketId math.Uint) []byte { var seq sequence.Sequence[math.Uint] - return append(CreatedObjectCountPrefix, seq.EncodeSequence(bucketId)...) + return append(LockedObjectCountPrefix, seq.EncodeSequence(bucketId)...) }