Skip to content

Commit

Permalink
add migration check and rebinding
Browse files Browse the repository at this point in the history
  • Loading branch information
fynnss committed Jun 19, 2023
1 parent a6857ab commit 80d3d74
Show file tree
Hide file tree
Showing 23 changed files with 932 additions and 751 deletions.
5 changes: 3 additions & 2 deletions e2e/tests/challenge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

sdkmath "cosmossdk.io/math"
"github.com/bits-and-blooms/bitset"
"github.com/bnb-chain/greenfield/types"
ctypes "github.com/cometbft/cometbft/rpc/core/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/suite"
Expand Down Expand Up @@ -107,10 +108,10 @@ func (s *ChallengeTestSuite) createObject() (string, string, sdk.AccAddress, []s
sp.OperatorKey.GetAddr(), sp.OperatorKey.GetAddr(),
}
msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvg.Id, nil)
sr := storagetypes.NewSecondarySpSignDoc(sp.OperatorKey.GetAddr(), queryHeadObjectResponse.ObjectInfo.Id, checksum)
sr := storagetypes.NewSecondarySpSignDoc(sp.Info.Id, queryHeadObjectResponse.ObjectInfo.Id, checksum)
secondarySig, err := sp.ApprovalKey.Sign(sr.GetSignBytes())
s.Require().NoError(err)
err = storagetypes.VerifySignature(sp.ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()), secondarySig)
err = types.VerifySignature(sp.ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()), secondarySig)
s.Require().NoError(err)

secondarySigs := [][]byte{secondarySig, secondarySig, secondarySig, secondarySig, secondarySig, secondarySig}
Expand Down
5 changes: 3 additions & 2 deletions e2e/tests/payment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"testing"
"time"

types2 "github.com/bnb-chain/greenfield/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
Expand Down Expand Up @@ -209,10 +210,10 @@ func (s *PaymentTestSuite) sealObject(bucketName, objectName string, objectId st
s.Require().True(found)

msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvg.Id, nil)
sr := storagetypes.NewSecondarySpSignDoc(sp.OperatorKey.GetAddr(), objectId, checksum)
sr := storagetypes.NewSecondarySpSignDoc(sp.Info.Id, objectId, checksum)
secondarySig, err := sp.ApprovalKey.Sign(sr.GetSignBytes())
s.Require().NoError(err)
err = storagetypes.VerifySignature(sp.ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()), secondarySig)
err = types2.VerifySignature(sp.ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()), secondarySig)
s.Require().NoError(err)

secondarySigs := [][]byte{secondarySig, secondarySig, secondarySig, secondarySig, secondarySig, secondarySig}
Expand Down
25 changes: 13 additions & 12 deletions e2e/tests/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"testing"
"time"

types2 "github.com/bnb-chain/greenfield/types"
virtualgroupmoduletypes "github.com/bnb-chain/greenfield/x/virtualgroup/types"

sdkmath "cosmossdk.io/math"
Expand Down Expand Up @@ -181,10 +182,10 @@ func (s *StorageTestSuite) TestCreateObject() {

// SealObject
msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvg.Id, nil)
sr := storagetypes.NewSecondarySpSignDoc(sp.OperatorKey.GetAddr(), queryHeadObjectResponse.ObjectInfo.Id, checksum)
sr := storagetypes.NewSecondarySpSignDoc(sp.Info.Id, queryHeadObjectResponse.ObjectInfo.Id, checksum)
secondarySig, err := sp.ApprovalKey.Sign(sr.GetSignBytes())
s.Require().NoError(err)
err = storagetypes.VerifySignature(s.StorageProviders[0].ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()),
err = types2.VerifySignature(s.StorageProviders[0].ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()),
secondarySig)
s.Require().NoError(err)

Expand Down Expand Up @@ -355,10 +356,10 @@ func (s *StorageTestSuite) TestDeleteBucket() {
// SealObject
msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName1, objectName,
gvg.Id, nil)
sr := storagetypes.NewSecondarySpSignDoc(sp.OperatorKey.GetAddr(), queryHeadObjectResponse.ObjectInfo.Id, checksum)
sr := storagetypes.NewSecondarySpSignDoc(sp.Info.Id, queryHeadObjectResponse.ObjectInfo.Id, checksum)
secondarySig, err := sp.ApprovalKey.Sign(sr.GetSignBytes())
s.Require().NoError(err)
err = storagetypes.VerifySignature(sp.ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()), secondarySig)
err = types2.VerifySignature(sp.ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()), secondarySig)
s.Require().NoError(err)

secondarySigs := [][]byte{secondarySig, secondarySig, secondarySig, secondarySig, secondarySig, secondarySig}
Expand Down Expand Up @@ -576,10 +577,10 @@ func (s *StorageTestSuite) TestPayment_Smoke() {
secondaryStorageProviders := s.StorageProviders[1:7]
msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvg.Id, nil)
secondarySigs := lo.Map(secondaryStorageProviders, func(sp core.StorageProvider, i int) []byte {
sr := storagetypes.NewSecondarySpSignDoc(sp.OperatorKey.GetAddr(), queryHeadObjectResponse.ObjectInfo.Id, checksum)
sr := storagetypes.NewSecondarySpSignDoc(sp.Info.Id, queryHeadObjectResponse.ObjectInfo.Id, checksum)
secondarySig, err := sp.ApprovalKey.Sign(sr.GetSignBytes())
s.Require().NoError(err)
err = storagetypes.VerifySignature(sp.ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()), secondarySig)
err = types2.VerifySignature(sp.ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()), secondarySig)
s.Require().NoError(err)
return secondarySig
})
Expand Down Expand Up @@ -965,10 +966,10 @@ func (s *StorageTestSuite) TestMirrorObject() {

// SealObject
msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvg.Id, nil)
sr := storagetypes.NewSecondarySpSignDoc(sp.OperatorKey.GetAddr(), queryHeadObjectResponse.ObjectInfo.Id, checksum)
sr := storagetypes.NewSecondarySpSignDoc(sp.Info.Id, queryHeadObjectResponse.ObjectInfo.Id, checksum)
secondarySig, err := sp.ApprovalKey.Sign(sr.GetSignBytes())
s.Require().NoError(err)
err = storagetypes.VerifySignature(s.StorageProviders[0].ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()),
err = types2.VerifySignature(s.StorageProviders[0].ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()),
secondarySig)
s.Require().NoError(err)

Expand Down Expand Up @@ -1012,10 +1013,10 @@ func (s *StorageTestSuite) TestMirrorObject() {

// SealObject
msgSealObject = storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvg.Id, nil)
sr = storagetypes.NewSecondarySpSignDoc(sp.OperatorKey.GetAddr(), queryHeadObjectResponse.ObjectInfo.Id, checksum)
sr = storagetypes.NewSecondarySpSignDoc(sp.Info.Id, queryHeadObjectResponse.ObjectInfo.Id, checksum)
secondarySig, err = sp.ApprovalKey.Sign(sr.GetSignBytes())
s.Require().NoError(err)
err = storagetypes.VerifySignature(s.StorageProviders[0].ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()),
err = types2.VerifySignature(s.StorageProviders[0].ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()),
secondarySig)
s.Require().NoError(err)

Expand Down Expand Up @@ -1438,10 +1439,10 @@ func (s *StorageTestSuite) createObjectWithVisibility(v storagetypes.VisibilityT

// SealObject
msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvg.Id, nil)
sr := storagetypes.NewSecondarySpSignDoc(sp.OperatorKey.GetAddr(), queryHeadObjectResponse.ObjectInfo.Id, checksum)
sr := storagetypes.NewSecondarySpSignDoc(sp.Info.Id, queryHeadObjectResponse.ObjectInfo.Id, checksum)
secondarySig, err := sp.ApprovalKey.Sign(sr.GetSignBytes())
s.Require().NoError(err)
err = storagetypes.VerifySignature(s.StorageProviders[0].ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()),
err = types2.VerifySignature(s.StorageProviders[0].ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()),
secondarySig)
s.Require().NoError(err)

Expand Down
10 changes: 0 additions & 10 deletions proto/greenfield/storage/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,3 @@ message SecondarySpSignDoc {
];
bytes checksum = 3;
}

message MigrationBucketSignDoc {
uint32 src_sp_id = 1;
uint32 dst_sp_id = 2;
string bucket_id = 3 [
(cosmos_proto.scalar) = "cosmos.Uint",
(gogoproto.customtype) = "Uint",
(gogoproto.nullable) = false
];
}
14 changes: 8 additions & 6 deletions proto/greenfield/storage/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -557,19 +557,21 @@ message MsgMigrateBucket {

message MsgMigrateBucketResponse {}


message LVGToGVGMapping {
uint32 local_virtual_group_id = 1;
uint32 global_virtual_group_id = 2;
repeated bytes secondary_sp_signature = 3;
}

message MsgCompleteMigrateBucket {
option (cosmos.msg.v1.signer) = "operator";

string operator = 1;

uint32 global_virtual_group_family_id =2;

message DstGVGInfo {
uint32 local_virtual_group_id = 1;
uint32 global_virtual_group_id = 2;
repeated bytes secondary_sp_signature = 3;
}
repeated DstGVGInfo dstGVGInfos = 3;
repeated LVGToGVGMapping new_lvg_to_gvg_mappings = 3;

string bucket_name = 4;
}
Expand Down
5 changes: 4 additions & 1 deletion proto/greenfield/virtualgroup/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,14 @@ message MsgWithdrawResponse {}
message MsgSwapOut {
option (cosmos.msg.v1.signer) = "operator_address";

// sp_address is the account address of the storage provider initiating the swap out.
// operator_address defines the account address of the storage provider initiating the swap out.
string operator_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// virtual_group_family_id is the identifier of the virtual group family.
// if it set to 0, it represents that the operator swap out as the primary storage provider
// it it set to non-zero, it represents that the operator swap out as the secondary storage provider.
uint32 virtual_group_family_id = 2;
// global_virtual_group_ids is a list of global virtual group IDs associated with the swap out.
// It allows to be empty only when the operator is the primary storage provider.
repeated uint32 global_virtual_group_ids = 3;
// successor_sp_id is the account address of the successor storage provider.
uint32 successor_sp_id = 4;
Expand Down
12 changes: 12 additions & 0 deletions proto/greenfield/virtualgroup/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,15 @@ message GVGStatisticsWithinSP {
uint32 storage_provider_id = 1;
uint32 secondary_count = 3;
}

message MigrationBucketSignDoc {
uint32 dst_primary_sp_id = 1;
uint32 local_virtual_group_id = 2;
uint32 src_global_virtual_group_id = 3;
uint32 dst_global_virtual_group_id = 4;
string bucket_id = 5 [
(cosmos_proto.scalar) = "cosmos.Uint",
(gogoproto.customtype) = "Uint",
(gogoproto.nullable) = false
];
}
48 changes: 48 additions & 0 deletions types/verifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package types

import (
"bytes"

"cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
)

func VerifySignature(sigAccAddress sdk.AccAddress, sigHash []byte, sig []byte) error {
if len(sig) != ethcrypto.SignatureLength {
return errors.Wrapf(sdkerrors.ErrorInvalidSigner, "signature length (actual: %d) doesn't match typical [R||S||V] signature 65 bytes", len(sig))
}
if sig[ethcrypto.RecoveryIDOffset] == 27 || sig[ethcrypto.RecoveryIDOffset] == 28 {
sig[ethcrypto.RecoveryIDOffset] -= 27
}
pubKeyBytes, err := secp256k1.RecoverPubkey(sigHash, sig)
if err != nil {
return errors.Wrap(err, "failed to recover delegated fee payer from sig")
}

ecPubKey, err := ethcrypto.UnmarshalPubkey(pubKeyBytes)
if err != nil {
return errors.Wrap(err, "failed to unmarshal recovered fee payer pubkey")
}

pubKeyAddr := ethcrypto.PubkeyToAddress(*ecPubKey)
if !bytes.Equal(pubKeyAddr.Bytes(), sigAccAddress.Bytes()) {
return errors.Wrapf(sdkerrors.ErrInvalidPubKey, "pubkey %s is different from approval pubkey %s", pubKeyAddr, sigAccAddress)
}

recoveredSignerAcc := sdk.AccAddress(pubKeyAddr.Bytes())

if !recoveredSignerAcc.Equals(sigAccAddress) {
return errors.Wrapf(sdkerrors.ErrorInvalidSigner, "failed to verify delegated fee payer %s signature", recoveredSignerAcc)
}

// VerifySignature of ethsecp256k1 accepts 64 byte signature [R||S]
// WARNING! Under NO CIRCUMSTANCES try to use pubKey.VerifySignature there
if !secp256k1.VerifySignature(pubKeyBytes, sigHash, sig[:len(sig)-1]) {
return errors.Wrap(sdkerrors.ErrorInvalidSigner, "unable to verify signer signature of EIP712 typed data")
}

return nil
}
3 changes: 2 additions & 1 deletion x/storage/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
"github.com/bnb-chain/greenfield/internal/sequence"
gnfdtypes "github.com/bnb-chain/greenfield/types"
"github.com/bnb-chain/greenfield/types/resource"
permtypes "github.com/bnb-chain/greenfield/x/permission/types"
sptypes "github.com/bnb-chain/greenfield/x/sp/types"
Expand Down Expand Up @@ -1331,7 +1332,7 @@ func (k Keeper) VerifySPAndSignature(ctx sdk.Context, spID uint32, sigData []byt

approvalAccAddress := sdk.MustAccAddressFromHex(sp.ApprovalAddress)

err := types.VerifySignature(approvalAccAddress, sdk.Keccak256(sigData), signature)
err := gnfdtypes.VerifySignature(approvalAccAddress, sdk.Keccak256(sigData), signature)
if err != nil {
return errors.Wrapf(types.ErrInvalidApproval, "verify signature error: %s", err)
}
Expand Down
14 changes: 10 additions & 4 deletions x/storage/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -623,8 +623,7 @@ func (k msgServer) MigrateBucket(goCtx context.Context, msg *types.MsgMigrateBuc
if msg.DstPrimarySpApproval.ExpiredHeight < (uint64)(ctx.BlockHeight()) {
return nil, types.ErrInvalidApproval.Wrap("dst primary sp approval timeout")
}
mgs := types.NewMigrationBucketSignDoc(srcSP.Id, dstSP.Id, bucketInfo.Id)
err := k.VerifySPAndSignature(ctx, dstSP.Id, mgs.GetSignBytes(), msg.DstPrimarySpApproval.Sig)
err := k.VerifySPAndSignature(ctx, dstSP.Id, msg.GetApprovalBytes(), msg.DstPrimarySpApproval.Sig)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -682,13 +681,20 @@ func (k msgServer) CompleteMigrateBucket(goCtx context.Context, msg *types.MsgCo

bucketInfo.PrimarySpId = migrationBucketInfo.DstSpId
bucketInfo.GlobalVirtualGroupFamilyId = msg.GlobalVirtualGroupFamilyId
k.SetBucketInfo(ctx, bucketInfo)
k.DeleteMigrationBucketInfo(ctx, bucketInfo.Id)

err := k.ChargeBucketMigration(ctx, oldBucketInfo, bucketInfo)
if err != nil {
return nil, types.ErrMigtationBucketFailed.Wrapf("update payment info failed.")
}

// rebinding gvg and lvg
err = k.virtualGroupKeeper.RebindingGVGsToBucket(ctx, bucketInfo.Id, dstSP, msg.NewLvgToGvgMappings)
if err != nil {
return nil, err
}

k.SetBucketInfo(ctx, bucketInfo)
k.DeleteMigrationBucketInfo(ctx, bucketInfo.Id)

return &types.MsgCompleteMigrateBucketResponse{}, nil
}
13 changes: 0 additions & 13 deletions x/storage/types/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,3 @@ func (sr *SecondarySpSignDoc) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(sr)
return sdk.MustSortJSON(bz)
}

func NewMigrationBucketSignDoc(srcSPID, dspSPID uint32, bucketID math.Uint) *MigrationBucketSignDoc {
return &MigrationBucketSignDoc{
SrcSpId: srcSPID,
DstSpId: dspSPID,
BucketId: bucketID,
}
}

func (mbs *MigrationBucketSignDoc) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(mbs)
return sdk.MustSortJSON(bz)
}
Loading

0 comments on commit 80d3d74

Please sign in to comment.