From 325e9449ca162f17cea17a291f4628a5d3c018a3 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Thu, 13 Jul 2023 17:25:25 +0800 Subject: [PATCH 01/33] feat: add testcases for payment related modules --- x/payment/keeper/stream_record.go | 15 +- x/payment/keeper/stream_record_test.go | 402 ++++++++++++++++++++++++- x/payment/module.go | 2 + x/payment/types/types_test.go | 12 + 4 files changed, 420 insertions(+), 11 deletions(-) create mode 100644 x/payment/types/types_test.go diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index 5765af0d4..5a75611a1 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -27,6 +27,9 @@ func (k Keeper) CheckStreamRecord(streamRecord *types.StreamRecord) { if streamRecord.NetflowRate.IsNil() { panic(fmt.Sprintf("invalid streamRecord netflowRate %s", streamRecord.NetflowRate)) } + if !streamRecord.FrozenNetflowRate.IsNil() && streamRecord.FrozenNetflowRate.IsPositive() { + panic(fmt.Sprintf("invalid streamRecord frozenNetflowRate %s", streamRecord.NetflowRate)) + } if streamRecord.LockBalance.IsNil() || streamRecord.LockBalance.IsNegative() { panic(fmt.Sprintf("invalid streamRecord lockBalance %s", streamRecord.LockBalance)) } @@ -178,7 +181,7 @@ func (k Keeper) UpdateStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe } } } - // if the change is a pay(which decreases the static balance or netflow rate), the left static balance should be enough + // if the change is a pay (which decreases the static balance or netflow rate), the left static balance should be enough if !forced && isPay && streamRecord.StaticBalance.IsNegative() { return fmt.Errorf("stream account %s balance not enough, lack of %s BNB", streamRecord.Account, streamRecord.StaticBalance.Abs()) } @@ -230,6 +233,7 @@ func (k Keeper) SettleStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe if payDuration.LTE(sdkmath.NewIntFromUint64(params.ForcedSettleTime)) { err := k.ForceSettle(ctx, streamRecord) if err != nil { + ctx.Logger().Error("fail to force settle stream record", "err", err, "record", streamRecord.Account) return err } } else { @@ -348,6 +352,7 @@ func (k Keeper) AutoSettle(ctx sdk.Context) { _, err := k.UpdateStreamRecordByAddr(ctx, flowChange) if err != nil { ctx.Logger().Error("auto settle, update stream record failed", "address", outFlow.ToAddress, "rate", outFlow.Rate.Neg()) + panic("should not happen") } flowStore.Delete(flowIterator.Key()) @@ -369,6 +374,7 @@ func (k Keeper) AutoSettle(ctx sdk.Context) { if !flowIterator.Valid() || finished { if !streamRecord.NetflowRate.IsZero() { ctx.Logger().Error("should not happen, stream netflow rate is not zero", "address", streamRecord.Account) + panic("should not happen") } k.RemoveAutoSettleRecord(ctx, record.Timestamp, addr) } @@ -382,8 +388,8 @@ func (k Keeper) TryResumeStreamRecord(ctx sdk.Context, streamRecord *types.Strea return fmt.Errorf("stream account %s status is not frozen", streamRecord.Account) } - if !streamRecord.NetflowRate.IsNil() && !streamRecord.NetflowRate.IsZero() { // the account is resuming - return fmt.Errorf("stream account %s status is resuming, although it is frozen now", streamRecord.Account) + if !streamRecord.NetflowRate.IsZero() { // the account is resuming or settling + return fmt.Errorf("stream account %s status is resuming or settling, please wait", streamRecord.Account) } params := k.GetParams(ctx) @@ -501,7 +507,7 @@ func (k Keeper) AutoResume(ctx sdk.Context) { _, err := k.UpdateStreamRecordByAddr(ctx, flowChange) if err != nil { ctx.Logger().Error("auto resume, update receiver stream record failed", "address", outFlow.ToAddress, "err", err.Error()) - break + panic("should not happen") } flowStore.Delete(flowIterator.Key()) @@ -528,6 +534,7 @@ func (k Keeper) AutoResume(ctx sdk.Context) { err := k.UpdateStreamRecord(ctx, streamRecord, change) if err != nil { ctx.Logger().Error("auto resume, update stream record failed", "err", err.Error()) + panic("should not happen") } k.RemoveAutoResumeRecord(ctx, record.Timestamp, addr) } diff --git a/x/payment/keeper/stream_record_test.go b/x/payment/keeper/stream_record_test.go index 5fddae9ae..a0f3a6030 100644 --- a/x/payment/keeper/stream_record_test.go +++ b/x/payment/keeper/stream_record_test.go @@ -14,7 +14,7 @@ import ( "github.com/bnb-chain/greenfield/x/payment/types" ) -func TestTryResumeStreamRecord_InResuming(t *testing.T) { +func TestTryResumeStreamRecord_InResumingOrSettling(t *testing.T) { keeper, ctx, _ := makePaymentKeeper(t) ctx = ctx.WithBlockTime(time.Now()) @@ -122,6 +122,109 @@ func TestTryResumeStreamRecord_ResumeInMultipleBlocks(t *testing.T) { } keeper.SetOutFlow(ctx, user, outFlow3) + // try to resume stream record + err := keeper.TryResumeStreamRecord(ctx, streamRecord, rate.SubRaw(10).MulRaw(int64(params.VersionedParams.ReserveTime))) + require.NoError(t, err) //only added static balance + found := keeper.ExistsAutoResumeRecord(ctx, ctx.BlockTime().Unix(), user) + require.True(t, !found) + streamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, streamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + + err = keeper.TryResumeStreamRecord(ctx, streamRecord, rate.MulRaw(int64(params.VersionedParams.ReserveTime))) + require.NoError(t, err) + + // still frozen + userStreamRecord, _ := keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + + _, found = keeper.GetAutoResumeRecord(ctx, ctx.BlockTime().Unix(), user) + require.True(t, found) + + // resume in end block + keeper.AutoResume(ctx) + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + + // resume in end block + keeper.AutoResume(ctx) + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + + // resume in end block + keeper.AutoResume(ctx) + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, userStreamRecord.NetflowRate, rate.Neg()) + require.Equal(t, userStreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) + + gvg1StreamRecord, _ := keeper.GetStreamRecord(ctx, gvg1) + require.True(t, gvg1StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, gvg1StreamRecord.NetflowRate, gvg1Rate) + require.Equal(t, gvg1StreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) + + gvg2StreamRecord, _ := keeper.GetStreamRecord(ctx, gvg2) + require.True(t, gvg2StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, gvg2StreamRecord.NetflowRate, gvg2Rate) + require.Equal(t, gvg2StreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) + + gvg3StreamRecord, _ := keeper.GetStreamRecord(ctx, gvg3) + require.True(t, gvg3StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, gvg3StreamRecord.NetflowRate, gvg3Rate) + require.Equal(t, gvg3StreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) +} + +func TestTryResumeStreamRecord_ResumeInMultipleBlocks_BalanceNotEnoughFinally(t *testing.T) { + keeper, ctx, depKeepers := makePaymentKeeper(t) + ctx = ctx.WithBlockTime(time.Now()) + + // resume account in multiple blocks + params := keeper.GetParams(ctx) + params.MaxAutoResumeFlowCount = 1 + _ = keeper.SetParams(ctx, params) + + rate := sdkmath.NewInt(300) + user := sample.RandAccAddress() + streamRecord := &types.StreamRecord{ + StaticBalance: sdkmath.ZeroInt(), + BufferBalance: sdkmath.ZeroInt(), + LockBalance: sdkmath.ZeroInt(), + Account: user.String(), + Status: types.STREAM_ACCOUNT_STATUS_FROZEN, + NetflowRate: sdkmath.NewInt(0), + FrozenNetflowRate: rate.Neg(), + OutFlowCount: 3, + } + keeper.SetStreamRecord(ctx, streamRecord) + + gvgAddress := []sdk.AccAddress{sample.RandAccAddress(), sample.RandAccAddress(), sample.RandAccAddress()} + + gvg1 := gvgAddress[0] + gvg1Rate := sdk.NewInt(50) + outFlow1 := &types.OutFlow{ + ToAddress: gvg1.String(), + Rate: gvg1Rate, + Status: types.OUT_FLOW_STATUS_FROZEN, + } + keeper.SetOutFlow(ctx, user, outFlow1) + + gvg2 := gvgAddress[1] + gvg2Rate := sdk.NewInt(100) + outFlow2 := &types.OutFlow{ + ToAddress: gvg2.String(), + Rate: gvg2Rate, + Status: types.OUT_FLOW_STATUS_FROZEN, + } + keeper.SetOutFlow(ctx, user, outFlow2) + + gvg3 := gvgAddress[2] + gvg3Rate := sdk.NewInt(150) + outFlow3 := &types.OutFlow{ + ToAddress: gvg3.String(), + Rate: gvg3Rate, + Status: types.OUT_FLOW_STATUS_FROZEN, + } + keeper.SetOutFlow(ctx, user, outFlow3) + err := keeper.TryResumeStreamRecord(ctx, streamRecord, rate.MulRaw(int64(params.VersionedParams.ReserveTime))) require.NoError(t, err) @@ -142,12 +245,24 @@ func TestTryResumeStreamRecord_ResumeInMultipleBlocks(t *testing.T) { userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + // time flies + timestamp := ctx.BlockTime().Unix() + int64(params.VersionedParams.ReserveTime)*2 + ctx = ctx.WithBlockTime(time.Unix(timestamp, 0)) + + depKeepers.AccountKeeper.EXPECT().HasAccount(gomock.Any(), gomock.Any()). + Return(true).AnyTimes() + depKeepers.BankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(errors.New("fail to transfer")).AnyTimes() + // resume in end block + ctx = ctx.WithValue(types.ForceUpdateStreamRecordKey, true) + keeper.AutoResume(ctx) userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) require.Equal(t, userStreamRecord.NetflowRate, rate.Neg()) require.Equal(t, userStreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) + require.True(t, userStreamRecord.StaticBalance.IsNegative()) // the static balance becomes negative gvg1StreamRecord, _ := keeper.GetStreamRecord(ctx, gvg1) require.True(t, gvg1StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) @@ -163,9 +278,128 @@ func TestTryResumeStreamRecord_ResumeInMultipleBlocks(t *testing.T) { require.True(t, gvg3StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) require.Equal(t, gvg3StreamRecord.NetflowRate, gvg3Rate) require.Equal(t, gvg3StreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) + + // there will be an auto settle record + autoSettles := keeper.GetAllAutoSettleRecord(ctx) + found = false + for _, settle := range autoSettles { + if settle.GetAddr() == user.String() { + found = true + } + } + require.True(t, found, "") + + keeper.AutoSettle(ctx) + keeper.AutoSettle(ctx) + keeper.AutoSettle(ctx) + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + require.Equal(t, userStreamRecord.NetflowRate, sdkmath.ZeroInt()) + require.Equal(t, userStreamRecord.FrozenNetflowRate, rate.Neg()) } -func TestAutoSettle_FreezeInOneBlock(t *testing.T) { +func TestAutoSettle_AccountIsInResuming(t *testing.T) { + keeper, ctx, _ := makePaymentKeeper(t) + ctx = ctx.WithBlockTime(time.Now()) + + // resume account in multiple blocks + params := keeper.GetParams(ctx) + params.MaxAutoResumeFlowCount = 1 + _ = keeper.SetParams(ctx, params) + + rate := sdkmath.NewInt(300) + user := sample.RandAccAddress() + streamRecord := &types.StreamRecord{ + StaticBalance: sdkmath.ZeroInt(), + BufferBalance: sdkmath.ZeroInt(), + LockBalance: sdkmath.ZeroInt(), + Account: user.String(), + Status: types.STREAM_ACCOUNT_STATUS_FROZEN, + NetflowRate: sdkmath.NewInt(0), + FrozenNetflowRate: rate.Neg(), + OutFlowCount: 3, + } + keeper.SetStreamRecord(ctx, streamRecord) + + gvgAddress := []sdk.AccAddress{sample.RandAccAddress(), sample.RandAccAddress(), sample.RandAccAddress()} + + gvg1 := gvgAddress[0] + gvg1Rate := sdk.NewInt(50) + outFlow1 := &types.OutFlow{ + ToAddress: gvg1.String(), + Rate: gvg1Rate, + Status: types.OUT_FLOW_STATUS_FROZEN, + } + keeper.SetOutFlow(ctx, user, outFlow1) + + gvg2 := gvgAddress[1] + gvg2Rate := sdk.NewInt(100) + outFlow2 := &types.OutFlow{ + ToAddress: gvg2.String(), + Rate: gvg2Rate, + Status: types.OUT_FLOW_STATUS_FROZEN, + } + keeper.SetOutFlow(ctx, user, outFlow2) + + gvg3 := gvgAddress[2] + gvg3Rate := sdk.NewInt(150) + outFlow3 := &types.OutFlow{ + ToAddress: gvg3.String(), + Rate: gvg3Rate, + Status: types.OUT_FLOW_STATUS_FROZEN, + } + keeper.SetOutFlow(ctx, user, outFlow3) + + err := keeper.TryResumeStreamRecord(ctx, streamRecord, rate.MulRaw(int64(params.VersionedParams.ReserveTime))) + require.NoError(t, err) + + // still frozen + userStreamRecord, _ := keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + + _, found := keeper.GetAutoResumeRecord(ctx, ctx.BlockTime().Unix(), user) + require.True(t, found) + + // add auto settle record + keeper.SetAutoSettleRecord(ctx, &types.AutoSettleRecord{ + Timestamp: ctx.BlockTime().Unix(), + Addr: user.String(), + }) + + keeper.AutoSettle(ctx) + keeper.AutoResume(ctx) + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + + keeper.AutoSettle(ctx) + keeper.AutoResume(ctx) + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + + keeper.AutoSettle(ctx) + keeper.AutoResume(ctx) + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, userStreamRecord.NetflowRate, rate.Neg()) + require.Equal(t, userStreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) + + gvg1StreamRecord, _ := keeper.GetStreamRecord(ctx, gvg1) + require.True(t, gvg1StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, gvg1StreamRecord.NetflowRate, gvg1Rate) + require.Equal(t, gvg1StreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) + + gvg2StreamRecord, _ := keeper.GetStreamRecord(ctx, gvg2) + require.True(t, gvg2StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, gvg2StreamRecord.NetflowRate, gvg2Rate) + require.Equal(t, gvg2StreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) + + gvg3StreamRecord, _ := keeper.GetStreamRecord(ctx, gvg3) + require.True(t, gvg3StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, gvg3StreamRecord.NetflowRate, gvg3Rate) + require.Equal(t, gvg3StreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) +} + +func TestAutoSettle_SettleInOneBlock(t *testing.T) { keeper, ctx, depKeepers := makePaymentKeeper(t) ctx = ctx.WithBlockTime(time.Now()) @@ -196,7 +430,7 @@ func TestAutoSettle_FreezeInOneBlock(t *testing.T) { LockBalance: sdkmath.ZeroInt(), Account: gvg.String(), Status: types.STREAM_ACCOUNT_STATUS_ACTIVE, - NetflowRate: sdkmath.NewInt(0), + NetflowRate: rate, FrozenNetflowRate: sdkmath.NewInt(0), OutFlowCount: 0, } @@ -226,7 +460,7 @@ func TestAutoSettle_FreezeInOneBlock(t *testing.T) { require.Equal(t, gvgOutFlow.Rate, rate) } -func TestAutoSettle_FreezeInMultipleBlocks(t *testing.T) { +func TestAutoSettle_SettleInMultipleBlocks(t *testing.T) { keeper, ctx, depKeepers := makePaymentKeeper(t) ctx = ctx.WithBlockTime(time.Now()) @@ -263,7 +497,7 @@ func TestAutoSettle_FreezeInMultipleBlocks(t *testing.T) { LockBalance: sdkmath.ZeroInt(), Account: gvg1.String(), Status: types.STREAM_ACCOUNT_STATUS_ACTIVE, - NetflowRate: sdkmath.NewInt(0), + NetflowRate: sdkmath.NewInt(50), FrozenNetflowRate: sdkmath.NewInt(0), OutFlowCount: 0, } @@ -283,7 +517,7 @@ func TestAutoSettle_FreezeInMultipleBlocks(t *testing.T) { LockBalance: sdkmath.ZeroInt(), Account: gvg2.String(), Status: types.STREAM_ACCOUNT_STATUS_ACTIVE, - NetflowRate: sdkmath.NewInt(0), + NetflowRate: sdkmath.NewInt(100), FrozenNetflowRate: sdkmath.NewInt(0), OutFlowCount: 0, } @@ -303,7 +537,7 @@ func TestAutoSettle_FreezeInMultipleBlocks(t *testing.T) { LockBalance: sdkmath.ZeroInt(), Account: gvg3.String(), Status: types.STREAM_ACCOUNT_STATUS_ACTIVE, - NetflowRate: sdkmath.NewInt(0), + NetflowRate: sdkmath.NewInt(150), FrozenNetflowRate: sdkmath.NewInt(0), OutFlowCount: 0, } @@ -355,3 +589,157 @@ func TestAutoSettle_FreezeInMultipleBlocks(t *testing.T) { require.Equal(t, gvg3OutFlow.Status, types.OUT_FLOW_STATUS_FROZEN) require.Equal(t, gvg3OutFlow.Rate, sdkmath.NewInt(150)) } + +func TestAutoSettle_SettleInMultipleBlocks_AutoResumeExists(t *testing.T) { + keeper, ctx, depKeepers := makePaymentKeeper(t) + ctx = ctx.WithBlockTime(time.Now()) + + // freeze account in multiple blocks + params := keeper.GetParams(ctx) + params.MaxAutoSettleFlowCount = 1 + params.MaxAutoResumeFlowCount = 1 + _ = keeper.SetParams(ctx, params) + + depKeepers.AccountKeeper.EXPECT().HasAccount(gomock.Any(), gomock.Any()). + Return(true).AnyTimes() + depKeepers.BankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(errors.New("fail to transfer")).AnyTimes() + + rate := sdkmath.NewInt(300) + user := sample.RandAccAddress() + userStreamRecord := &types.StreamRecord{ + StaticBalance: sdkmath.ZeroInt(), + BufferBalance: sdkmath.ZeroInt(), + LockBalance: sdkmath.ZeroInt(), + Account: user.String(), + Status: types.STREAM_ACCOUNT_STATUS_FROZEN, + NetflowRate: sdk.ZeroInt(), + FrozenNetflowRate: rate.Neg(), + OutFlowCount: 3, + } + keeper.SetStreamRecord(ctx, userStreamRecord) + + gvgAddress := []sdk.AccAddress{sample.RandAccAddress(), sample.RandAccAddress(), sample.RandAccAddress()} + + gvg1 := gvgAddress[0] + gvg1StreamRecord := &types.StreamRecord{ + StaticBalance: sdkmath.ZeroInt(), + BufferBalance: sdkmath.ZeroInt(), + LockBalance: sdkmath.ZeroInt(), + Account: gvg1.String(), + Status: types.STREAM_ACCOUNT_STATUS_ACTIVE, + NetflowRate: sdkmath.NewInt(0), + FrozenNetflowRate: sdkmath.NewInt(0), + OutFlowCount: 0, + } + keeper.SetStreamRecord(ctx, gvg1StreamRecord) + + outFlow1 := &types.OutFlow{ + ToAddress: gvg1.String(), + Rate: sdkmath.NewInt(50), + Status: types.OUT_FLOW_STATUS_FROZEN, + } + keeper.SetOutFlow(ctx, user, outFlow1) + + gvg2 := gvgAddress[1] + gvg2StreamRecord := &types.StreamRecord{ + StaticBalance: sdkmath.ZeroInt(), + BufferBalance: sdkmath.ZeroInt(), + LockBalance: sdkmath.ZeroInt(), + Account: gvg2.String(), + Status: types.STREAM_ACCOUNT_STATUS_ACTIVE, + NetflowRate: sdkmath.NewInt(0), + FrozenNetflowRate: sdkmath.NewInt(0), + OutFlowCount: 0, + } + keeper.SetStreamRecord(ctx, gvg2StreamRecord) + + outFlow2 := &types.OutFlow{ + ToAddress: gvg2.String(), + Rate: sdkmath.NewInt(100), + Status: types.OUT_FLOW_STATUS_FROZEN, + } + keeper.SetOutFlow(ctx, user, outFlow2) + + gvg3 := gvgAddress[2] + gvg3StreamRecord := &types.StreamRecord{ + StaticBalance: sdkmath.ZeroInt(), + BufferBalance: sdkmath.ZeroInt(), + LockBalance: sdkmath.ZeroInt(), + Account: gvg3.String(), + Status: types.STREAM_ACCOUNT_STATUS_ACTIVE, + NetflowRate: sdkmath.NewInt(0), + FrozenNetflowRate: sdkmath.NewInt(0), + OutFlowCount: 0, + } + keeper.SetStreamRecord(ctx, gvg3StreamRecord) + + outFlow3 := &types.OutFlow{ + ToAddress: gvg3.String(), + Rate: sdkmath.NewInt(150), + Status: types.OUT_FLOW_STATUS_FROZEN, + } + keeper.SetOutFlow(ctx, user, outFlow3) + + // resume the stream record + err := keeper.TryResumeStreamRecord(ctx, userStreamRecord, rate.MulRaw(int64(params.VersionedParams.ReserveTime))) + require.NoError(t, err) //only added static balance + found := keeper.ExistsAutoResumeRecord(ctx, ctx.BlockTime().Unix(), user) + require.True(t, found) + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + + // add auto settle record + settleTime := ctx.BlockTime().Unix() + keeper.SetAutoSettleRecord(ctx, &types.AutoSettleRecord{ + Timestamp: settleTime, + Addr: user.String(), + }) + + keeper.AutoSettle(ctx) // this is for settle stream, it is counted + keeper.AutoSettle(ctx) + keeper.AutoSettle(ctx) + keeper.AutoSettle(ctx) + keeper.AutoSettle(ctx) + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) + + keeper.AutoResume(ctx) + keeper.AutoResume(ctx) + keeper.AutoResume(ctx) + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + + timestamp := ctx.BlockTime().Unix() + ctx = ctx.WithBlockTime(time.Unix(timestamp+10, 0)) + keeper.AutoSettle(ctx) // it will pick up the auto settle record + autoSettles := keeper.GetAllAutoSettleRecord(ctx) + var record types.AutoSettleRecord + for _, settle := range autoSettles { + if settle.GetAddr() == user.String() { + record = settle + } + } + // old settle record removed, new settle record added + require.True(t, record.Timestamp != settleTime, "") + + userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.True(t, userStreamRecord.NetflowRate.Equal(rate.Neg())) + require.True(t, userStreamRecord.FrozenNetflowRate.IsZero()) + + gvg1StreamRecord, _ = keeper.GetStreamRecord(ctx, gvg1) + require.True(t, gvg1StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, gvg1StreamRecord.NetflowRate, sdk.NewInt(50)) + require.Equal(t, gvg1StreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) + + gvg2StreamRecord, _ = keeper.GetStreamRecord(ctx, gvg2) + require.True(t, gvg2StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, gvg2StreamRecord.NetflowRate, sdk.NewInt(100)) + require.Equal(t, gvg2StreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) + + gvg3StreamRecord, _ = keeper.GetStreamRecord(ctx, gvg3) + require.True(t, gvg3StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.Equal(t, gvg3StreamRecord.NetflowRate, sdk.NewInt(150)) + require.Equal(t, gvg3StreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) +} diff --git a/x/payment/module.go b/x/payment/module.go index 228832500..3dc2e77e5 100644 --- a/x/payment/module.go +++ b/x/payment/module.go @@ -145,6 +145,8 @@ func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} // EndBlock contains the logic that is automatically triggered at the end of each block func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + // set ForceUpdateStreamRecordKey to true in context to force update frozen stream record + ctx = ctx.WithValue(types.ForceUpdateStreamRecordKey, true) am.keeper.AutoResume(ctx) am.keeper.AutoSettle(ctx) return []abci.ValidatorUpdate{} diff --git a/x/payment/types/types_test.go b/x/payment/types/types_test.go new file mode 100644 index 000000000..70eae0762 --- /dev/null +++ b/x/payment/types/types_test.go @@ -0,0 +1,12 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestVerifyModuleAddress(t *testing.T) { + require.Equal(t, "0x25b2f7C1aA3cCCeF718e8e3A7Ec1A7C521eef2a9", GovernanceAddress.String()) + require.Equal(t, "0xdF5F0588f6B09f0B9E58D3426252db25Dc74E7a1", ValidatorTaxPoolAddress.String()) +} From a44ca26794a88d0e3a536b51f8efcefc37f44132 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Fri, 14 Jul 2023 11:28:18 +0800 Subject: [PATCH 02/33] add testcases and refactor --- e2e/tests/payment_test.go | 1164 ++++++++++++++++++++++-------- x/storage/keeper/payment.go | 36 +- x/storage/keeper/payment_test.go | 40 +- 3 files changed, 904 insertions(+), 336 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index a01607503..e4d4900a8 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -10,17 +10,9 @@ import ( "testing" "time" - sdkmath "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/tx" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/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/samber/lo" "github.com/stretchr/testify/suite" + sdkmath "cosmossdk.io/math" "github.com/bnb-chain/greenfield/e2e/core" "github.com/bnb-chain/greenfield/sdk/keys" "github.com/bnb-chain/greenfield/sdk/types" @@ -29,7 +21,15 @@ import ( paymenttypes "github.com/bnb-chain/greenfield/x/payment/types" sptypes "github.com/bnb-chain/greenfield/x/sp/types" storagetypes "github.com/bnb-chain/greenfield/x/storage/types" - virtualgroupmoduletypes "github.com/bnb-chain/greenfield/x/virtualgroup/types" + virtualgrouptypes "github.com/bnb-chain/greenfield/x/virtualgroup/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/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/samber/lo" ) type StreamRecords struct { @@ -88,241 +88,6 @@ func (s *PaymentTestSuite) TestPaymentAccount() { s.Require().Equal(false, paymentAccount.PaymentAccount.Refundable) } -func (s *PaymentTestSuite) updateParams(params paymenttypes.Params) { - var err error - validator := s.Validator.GetAddr() - - ctx := context.Background() - - ts := time.Now().Unix() - queryParamsRequest := &paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, queryParamsRequest) - s.Require().NoError(err) - - msgUpdateParams := &paymenttypes.MsgUpdateParams{ - Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), - Params: params, - } - - msgProposal, err := govtypesv1.NewMsgSubmitProposal( - []sdk.Msg{msgUpdateParams}, - sdk.Coins{sdk.NewCoin(s.BaseSuite.Config.Denom, types.NewIntFromInt64WithDecimal(100, types.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) - - queryParamsByTimestampRequest := &paymenttypes.QueryParamsByTimestampRequest{Timestamp: ts} - queryParamsByTimestampResponse, err := s.Client.PaymentQueryClient.ParamsByTimestamp(ctx, queryParamsByTimestampRequest) - s.Require().NoError(err) - s.Require().Equal(queryParamsResponse.Params.VersionedParams.ReserveTime, - queryParamsByTimestampResponse.Params.VersionedParams.ReserveTime) - s.T().Logf("new params: %s", params.String()) -} - -func (s *PaymentTestSuite) createBucketAndObject() (keys.KeyManager, string, string, storagetypes.Uint, [][]byte) { - var err error - sp := s.StorageProviders[0] - gvg, found := sp.GetFirstGlobalVirtualGroup() - s.Require().True(found) - - // CreateBucket - user := s.GenAndChargeAccounts(1, 1000000)[0] - bucketName := "ch" + storagetestutils.GenRandomBucketName() - msgCreateBucket := storagetypes.NewMsgCreateBucket( - user.GetAddr(), bucketName, storagetypes.VISIBILITY_TYPE_PRIVATE, 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) - - // CreateObject - objectName := storagetestutils.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(context.Background(), &queryHeadObjectRequest) - s.Require().NoError(err) - s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectName, objectName) - s.Require().Equal(queryHeadObjectResponse.ObjectInfo.BucketName, bucketName) - - return user, bucketName, objectName, queryHeadObjectResponse.ObjectInfo.Id, expectChecksum -} - -func (s *PaymentTestSuite) createBucket() (keys.KeyManager, string) { - var err error - sp := s.StorageProviders[0] - gvg, found := sp.GetFirstGlobalVirtualGroup() - s.Require().True(found) - - // CreateBucket - user := s.GenAndChargeAccounts(1, 1000000)[0] - bucketName := "ch" + storagetestutils.GenRandomBucketName() - msgCreateBucket := storagetypes.NewMsgCreateBucket( - user.GetAddr(), bucketName, storagetypes.VISIBILITY_TYPE_PRIVATE, 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) - - return user, bucketName -} - -func (s *PaymentTestSuite) createObject(user keys.KeyManager, bucketName string) (keys.KeyManager, string, string, storagetypes.Uint, [][]byte) { - var err error - sp := s.StorageProviders[0] - - // CreateObject - objectName := storagetestutils.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(context.Background(), &queryHeadObjectRequest) - s.Require().NoError(err) - s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectName, objectName) - s.Require().Equal(queryHeadObjectResponse.ObjectInfo.BucketName, bucketName) - - return user, bucketName, objectName, queryHeadObjectResponse.ObjectInfo.Id, expectChecksum -} - -func (s *PaymentTestSuite) sealObject(bucketName, objectName string, objectId storagetypes.Uint, checksums [][]byte) { - sp := s.StorageProviders[0] - gvg, found := sp.GetFirstGlobalVirtualGroup() - s.Require().True(found) - s.T().Log("GVG info: ", gvg.String()) - - // SealObject - gvgId := gvg.Id - msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvg.Id, nil) - secondarySigs := make([][]byte, 0) - secondarySPBlsPubKeys := make([]bls.PublicKey, 0) - blsSignHash := storagetypes.NewSecondarySpSealObjectSignDoc(s.GetChainID(), gvgId, objectId, storagetypes.GenerateHash(checksums[:])).GetBlsSignHash() - // every secondary sp signs the checksums - for i := 1; i < len(s.StorageProviders); i++ { - sig, err := core.BlsSignAndVerify(s.StorageProviders[i], blsSignHash) - s.Require().NoError(err) - secondarySigs = append(secondarySigs, sig) - pk, err := bls.PublicKeyFromBytes(s.StorageProviders[i].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) - - queryHeadObjectRequest2 := storagetypes.QueryHeadObjectRequest{ - BucketName: bucketName, - ObjectName: objectName, - } - queryHeadObjectResponse2, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest2) - s.Require().NoError(err) - s.Require().Equal(queryHeadObjectResponse2.ObjectInfo.ObjectName, objectName) - s.Require().Equal(queryHeadObjectResponse2.ObjectInfo.BucketName, bucketName) - s.Require().Equal(queryHeadObjectResponse2.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) -} - // TestVersionedParams_SealAfterReserveTimeChange will cover the following case: // create an object, increase the reserve time, seal the object without error. func (s *PaymentTestSuite) TestVersionedParams_SealObjectAfterReserveTimeChange() { @@ -581,7 +346,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InOneBlock() { s.SendTxBlock(user, msgCreateBucket) // check payment account stream record - paymentAccountStreamRecord := s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecord := s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecord %s", core.YamlString(paymentAccountStreamRecord)) s.Require().Equal(expectedRate.String(), paymentAccountStreamRecord.NetflowRate.Neg().String()) s.Require().Equal(paymentAccountStreamRecord.BufferBalance.String(), paymentAccountBNBNeeded.String()) @@ -604,7 +369,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InOneBlock() { } } // check auto settle - paymentStreamRecordAfterAutoSettle := s.GetStreamRecord(paymentAddr) + paymentStreamRecordAfterAutoSettle := s.getStreamRecord(paymentAddr) s.T().Logf("paymentStreamRecordAfterAutoSettle %s", core.YamlString(paymentStreamRecordAfterAutoSettle)) s.Require().NotEqual(paymentStreamRecordAfterAutoSettle.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) @@ -618,7 +383,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InOneBlock() { _ = s.SendTxBlock(user, msgDeposit1) // check payment account stream record - paymentAccountStreamRecordAfterDeposit1 := s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecordAfterDeposit1 := s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecordAfterDeposit1 %s", core.YamlString(paymentAccountStreamRecordAfterDeposit1)) s.Require().NotEqual(paymentAccountStreamRecordAfterDeposit1.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) @@ -631,7 +396,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InOneBlock() { } s.SendTxBlock(user, msgDeposit2) // check payment account stream record - paymentAccountStreamRecordAfterDeposit2 := s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecordAfterDeposit2 := s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecordAfterDeposit2 %s", core.YamlString(paymentAccountStreamRecordAfterDeposit2)) s.Require().Equal(paymentAccountStreamRecordAfterDeposit2.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) s.Require().Equal(paymentAccountStreamRecordAfterDeposit2.StaticBalance.Add(paymentAccountStreamRecordAfterDeposit2.BufferBalance).String(), paymentAccountStreamRecordAfterDeposit1.StaticBalance.Add(depositAmount2).String()) @@ -706,7 +471,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InBlocks() { s.SendTxBlock(user, msgCreateBucket) // check payment account stream record - paymentAccountStreamRecord := s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecord := s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecord %s", core.YamlString(paymentAccountStreamRecord)) s.Require().Equal(expectedRate.String(), paymentAccountStreamRecord.NetflowRate.Neg().String()) s.Require().Equal(paymentAccountStreamRecord.BufferBalance.String(), paymentAccountBNBNeeded.String()) @@ -729,7 +494,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InBlocks() { } } // check auto settle - paymentStreamRecordAfterAutoSettle := s.GetStreamRecord(paymentAddr) + paymentStreamRecordAfterAutoSettle := s.getStreamRecord(paymentAddr) s.T().Logf("paymentStreamRecordAfterAutoSettle %s", core.YamlString(paymentStreamRecordAfterAutoSettle)) s.Require().NotEqual(paymentStreamRecordAfterAutoSettle.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) @@ -748,7 +513,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InBlocks() { s.SendTxWithTxOpt(msgDeposit, user, txOpt) // check payment account stream record - paymentAccountStreamRecordAfterDeposit := s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecordAfterDeposit := s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecordAfterDeposit %s", core.YamlString(paymentAccountStreamRecordAfterDeposit)) s.Require().NotEqual(paymentAccountStreamRecordAfterDeposit.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) @@ -757,7 +522,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InBlocks() { latestBlock, err := s.TmClient.TmClient.Block(ctx, nil) s.Require().NoError(err) - paymentAccountStreamRecordAfterDeposit = s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecordAfterDeposit = s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecordAfterDeposit %s at %d", core.YamlString(paymentAccountStreamRecordAfterDeposit), latestBlock.Block.Height) if paymentAccountStreamRecordAfterDeposit.Status == paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE { break @@ -783,7 +548,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { userAddr := user.GetAddr().String() var err error - queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgroupmoduletypes.QueryGlobalVirtualGroupFamilyRequest{ + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ StorageProviderId: sp.Info.Id, FamilyId: gvg.FamilyId, }) @@ -836,7 +601,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { s.Require().NoError(err) s.SendTxBlock(user, msgCreateBucket) // check payment account stream record - paymentAccountStreamRecord := s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecord := s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecord %s", core.YamlString(paymentAccountStreamRecord)) s.Require().Equal(expectedRate.String(), paymentAccountStreamRecord.NetflowRate.Neg().String()) s.Require().Equal(paymentAccountStreamRecord.BufferBalance.String(), paymentAccountBNBNeeded.String()) @@ -861,12 +626,12 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { s.SendTxBlock(user, msgCreateBucket) // check user stream record - userStreamRecord := s.GetStreamRecord(userAddr) + userStreamRecord := s.getStreamRecord(userAddr) s.T().Logf("userStreamRecord %s", core.YamlString(userStreamRecord)) s.Require().Equal(userStreamRecord.SettleTimestamp, userStreamRecord.CrudTimestamp+int64(reserveTime-forcedSettleTime)) - familyStreamRecord := s.GetStreamRecord(family.VirtualPaymentAddress) + familyStreamRecord := s.getStreamRecord(family.VirtualPaymentAddress) s.T().Logf("familyStreamRecord %s", core.YamlString(familyStreamRecord)) - govStreamRecord := s.GetStreamRecord(paymenttypes.GovernanceAddress.String()) + govStreamRecord := s.getStreamRecord(paymenttypes.GovernanceAddress.String()) s.T().Logf("govStreamRecord %s", core.YamlString(govStreamRecord)) // wait until settle time @@ -886,11 +651,11 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { } } // check auto settle - userStreamRecordAfterAutoSettle := s.GetStreamRecord(userAddr) + userStreamRecordAfterAutoSettle := s.getStreamRecord(userAddr) s.T().Logf("userStreamRecordAfterAutoSettle %s", core.YamlString(userStreamRecordAfterAutoSettle)) - familyStreamRecordAfterAutoSettle := s.GetStreamRecord(family.VirtualPaymentAddress) + familyStreamRecordAfterAutoSettle := s.getStreamRecord(family.VirtualPaymentAddress) s.T().Logf("familyStreamRecordAfterAutoSettle %s", core.YamlString(familyStreamRecordAfterAutoSettle)) - paymentAccountStreamRecordAfterAutoSettle := s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecordAfterAutoSettle := s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecordAfterAutoSettle %s", core.YamlString(paymentAccountStreamRecordAfterAutoSettle)) // payment account become frozen s.Require().NotEqual(paymentAccountStreamRecordAfterAutoSettle.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) @@ -900,7 +665,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { s.Require().NotEqual(userStreamRecordAfterAutoSettle.SettleTimestamp, userStreamRecord.SettleTimestamp) s.Require().Equal(userStreamRecordAfterAutoSettle.SettleTimestamp, userStreamRecordAfterAutoSettle.CrudTimestamp+int64(reserveTime-forcedSettleTime)) // gov stream record balance increase - govStreamRecordAfterSettle := s.GetStreamRecord(paymenttypes.GovernanceAddress.String()) + govStreamRecordAfterSettle := s.getStreamRecord(paymenttypes.GovernanceAddress.String()) s.T().Logf("govStreamRecordAfterSettle %s", core.YamlString(govStreamRecordAfterSettle)) s.Require().NotEqual(govStreamRecordAfterSettle.StaticBalance.String(), govStreamRecord.StaticBalance.String()) govStreamRecordStaticBalanceDelta := govStreamRecordAfterSettle.StaticBalance.Sub(govStreamRecord.StaticBalance) @@ -916,7 +681,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { } _ = s.SendTxBlock(user, msgDeposit1) // check payment account stream record - paymentAccountStreamRecordAfterDeposit1 := s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecordAfterDeposit1 := s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecordAfterDeposit1 %s", core.YamlString(paymentAccountStreamRecordAfterDeposit1)) s.Require().NotEqual(paymentAccountStreamRecordAfterDeposit1.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) s.Require().Equal(paymentAccountStreamRecordAfterDeposit1.StaticBalance.String(), paymentAccountStreamRecordAfterAutoSettle.StaticBalance.Add(depositAmount1).String()) @@ -930,7 +695,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { } s.SendTxBlock(user, msgDeposit2) // check payment account stream record - paymentAccountStreamRecordAfterDeposit2 := s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecordAfterDeposit2 := s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecordAfterDeposit2 %s", core.YamlString(paymentAccountStreamRecordAfterDeposit2)) s.Require().Equal(paymentAccountStreamRecordAfterDeposit2.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) s.Require().Equal(paymentAccountStreamRecordAfterDeposit2.StaticBalance.Add(paymentAccountStreamRecordAfterDeposit2.BufferBalance).String(), paymentAccountStreamRecordAfterDeposit1.StaticBalance.Add(depositAmount2).String()) @@ -1005,7 +770,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InBlocks() { s.SendTxBlock(user, msgCreateBucket) // check payment account stream record - paymentAccountStreamRecord := s.GetStreamRecord(paymentAddr) + paymentAccountStreamRecord := s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecord %s", core.YamlString(paymentAccountStreamRecord)) s.Require().Equal(expectedRate.String(), paymentAccountStreamRecord.NetflowRate.Neg().String()) s.Require().Equal(paymentAccountStreamRecord.BufferBalance.String(), paymentAccountBNBNeeded.String()) @@ -1029,7 +794,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InBlocks() { } // check auto settle for { - paymentStreamRecordAfterAutoSettle := s.GetStreamRecord(paymentAddr) + paymentStreamRecordAfterAutoSettle := s.getStreamRecord(paymentAddr) s.T().Logf("paymentStreamRecordAfterAutoSettle %s", core.YamlString(paymentStreamRecordAfterAutoSettle)) if paymentStreamRecordAfterAutoSettle.NetflowRate.IsZero() { break @@ -1040,7 +805,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InBlocks() { s.T().Fatalf("wait for settle time timeout") } } - paymentStreamRecordAfterAutoSettle := s.GetStreamRecord(paymentAddr) + paymentStreamRecordAfterAutoSettle := s.getStreamRecord(paymentAddr) s.T().Logf("paymentStreamRecordAfterAutoSettle %s", core.YamlString(paymentStreamRecordAfterAutoSettle)) s.Require().NotEqual(paymentStreamRecordAfterAutoSettle.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) @@ -1055,7 +820,7 @@ func (s *PaymentTestSuite) TestDeleteBucketWithReadQuota() { sp := s.StorageProviders[0] gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) - queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgroupmoduletypes.QueryGlobalVirtualGroupFamilyRequest{ + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ StorageProviderId: sp.Info.Id, FamilyId: gvg.FamilyId, }) @@ -1081,7 +846,7 @@ func (s *PaymentTestSuite) TestDeleteBucketWithReadQuota() { s.Require().NoError(err) s.SendTxBlock(user, msgCreateBucket) - streamRecordsBeforeDelete := s.GetStreamRecords(streamAddresses) + streamRecordsBeforeDelete := s.getStreamRecords(streamAddresses) s.T().Logf("streamRecordsBeforeDelete: %s", core.YamlString(streamRecordsBeforeDelete)) s.Require().NotEqual(streamRecordsBeforeDelete.User.NetflowRate.String(), "0") @@ -1090,7 +855,7 @@ func (s *PaymentTestSuite) TestDeleteBucketWithReadQuota() { s.SendTxBlock(user, msgDeleteBucket) // check the billing change - streamRecordsAfterDelete := s.GetStreamRecords(streamAddresses) + streamRecordsAfterDelete := s.getStreamRecords(streamAddresses) s.T().Logf("streamRecordsBeforeDelete: %s", core.YamlString(streamRecordsAfterDelete)) s.Require().Equal(streamRecordsAfterDelete.User.NetflowRate.String(), "0") } @@ -1101,7 +866,7 @@ func (s *PaymentTestSuite) TestStorageSmoke() { sp := s.StorageProviders[0] gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) - queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgroupmoduletypes.QueryGlobalVirtualGroupFamilyRequest{ + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ StorageProviderId: sp.Info.Id, FamilyId: gvg.FamilyId, }) @@ -1115,7 +880,7 @@ func (s *PaymentTestSuite) TestStorageSmoke() { gvg.VirtualPaymentAddress, paymenttypes.ValidatorTaxPoolAddress.String(), } - streamRecordsBeforeCreateBucket := s.GetStreamRecords(streamAddresses) + streamRecordsBeforeCreateBucket := s.getStreamRecords(streamAddresses) s.T().Logf("streamRecordsBeforeCreateBucket: %s", core.YamlString(streamRecordsBeforeCreateBucket)) paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) @@ -1142,7 +907,7 @@ func (s *PaymentTestSuite) TestStorageSmoke() { s.Require().NoError(err) s.T().Logf("user bank account %s", userBankAccount) - streamRecordsAfterCreateBucket := s.GetStreamRecords(streamAddresses) + streamRecordsAfterCreateBucket := s.getStreamRecords(streamAddresses) userStreamRecord := streamRecordsAfterCreateBucket.User s.Require().Equal(userStreamRecord.StaticBalance, sdkmath.ZeroInt()) @@ -1229,11 +994,11 @@ func (s *PaymentTestSuite) TestStorageSmoke() { s.Require().NoError(err) primaryStorePrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.StorePrice secondaryStorePrice := queryGetSecondarySpStorePriceByTime.SecondarySpStorePrice.StorePrice - chargeSize := s.GetChargeSize(queryHeadObjectResponse.ObjectInfo.PayloadSize) + chargeSize := s.getChargeSize(queryHeadObjectResponse.ObjectInfo.PayloadSize) expectedChargeRate := primaryStorePrice.Add(secondaryStorePrice.MulInt64(6)).MulInt(sdk.NewIntFromUint64(chargeSize)).TruncateInt() expectedLockedBalance := expectedChargeRate.Mul(sdkmath.NewIntFromUint64(paymentParams.Params.VersionedParams.ReserveTime)) - streamRecordsAfterCreateObject := s.GetStreamRecords(streamAddresses) + streamRecordsAfterCreateObject := s.getStreamRecords(streamAddresses) s.T().Logf("streamRecordsAfterCreateObject %s", core.YamlString(streamRecordsAfterCreateObject)) userStreamAccountAfterCreateObj := streamRecordsAfterCreateObject.User @@ -1261,10 +1026,10 @@ func (s *PaymentTestSuite) TestStorageSmoke() { s.SendTxBlock(sp.SealKey, msgSealObject) // check bill after seal - streamRecordsAfterSeal := s.GetStreamRecords(streamAddresses) + streamRecordsAfterSeal := s.getStreamRecords(streamAddresses) s.T().Logf("streamRecordsAfterSeal %s", core.YamlString(streamRecordsAfterSeal)) s.Require().Equal(sdkmath.ZeroInt(), streamRecordsAfterSeal.User.LockBalance) - s.CheckStreamRecordsBeforeAndAfter(streamRecordsAfterCreateObject, streamRecordsAfterSeal, readPrice, readChargeRate, primaryStorePrice, secondaryStorePrice, chargeSize, uint64(payloadSize)) + s.checkStreamRecordsBeforeAndAfter(streamRecordsAfterCreateObject, streamRecordsAfterSeal, readPrice, readChargeRate, primaryStorePrice, secondaryStorePrice, chargeSize, uint64(payloadSize)) // query dynamic balance time.Sleep(3 * time.Second) @@ -1276,7 +1041,7 @@ func (s *PaymentTestSuite) TestStorageSmoke() { s.T().Logf("queryDynamicBalanceResponse %s", core.YamlString(queryDynamicBalanceResponse)) // create empty object - streamRecordsBeforeCreateEmptyObject := s.GetStreamRecords(streamAddresses) + streamRecordsBeforeCreateEmptyObject := s.getStreamRecords(streamAddresses) s.T().Logf("streamRecordsBeforeCreateEmptyObject %s", core.YamlString(streamRecordsBeforeCreateEmptyObject)) emptyObjectName := "sub_directory/" @@ -1290,10 +1055,10 @@ func (s *PaymentTestSuite) TestStorageSmoke() { s.Require().NoError(err) s.SendTxBlock(user, msgCreateEmptyObject) - streamRecordsAfterCreateEmptyObject := s.GetStreamRecords(streamAddresses) + streamRecordsAfterCreateEmptyObject := s.getStreamRecords(streamAddresses) s.T().Logf("streamRecordsAfterCreateEmptyObject %s", core.YamlString(streamRecordsAfterCreateEmptyObject)) - chargeSize = s.GetChargeSize(uint64(emptyPayloadSize)) - s.CheckStreamRecordsBeforeAndAfter(streamRecordsBeforeCreateEmptyObject, streamRecordsAfterCreateEmptyObject, readPrice, readChargeRate, primaryStorePrice, secondaryStorePrice, chargeSize, uint64(emptyPayloadSize)) + chargeSize = s.getChargeSize(uint64(emptyPayloadSize)) + s.checkStreamRecordsBeforeAndAfter(streamRecordsBeforeCreateEmptyObject, streamRecordsAfterCreateEmptyObject, readPrice, readChargeRate, primaryStorePrice, secondaryStorePrice, chargeSize, uint64(emptyPayloadSize)) // test query auto settle records queryAllAutoSettleRecordRequest := paymenttypes.QueryAllAutoSettleRecordRequest{} @@ -1322,14 +1087,15 @@ func (s *PaymentTestSuite) TestForceDeletion_AfterPriceChange() { s.Require().NoError(err) s.T().Log("price", priceRes.SpStoragePrice) + user := s.GenAndChargeAccounts(1, 1000000)[0] // create bucket - user, bucketName := s.createBucket() + bucketName := s.createBucket(user, 0) // create & seal objects - _, _, objectName1, objectId1, checksums1 := s.createObject(user, bucketName) + _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) s.sealObject(bucketName, objectName1, objectId1, checksums1) - _, _, objectName2, objectId2, checksums2 := s.createObject(user, bucketName) + _, _, objectName2, objectId2, checksums2, _ := s.createObject(user, bucketName, false) s.sealObject(bucketName, objectName2, objectId2, checksums2) // update new price @@ -1404,13 +1170,387 @@ func (s *PaymentTestSuite) TestForceDeletion_AfterPriceChange() { s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) } -func (s *PaymentTestSuite) GetStreamRecord(addr string) (sr paymenttypes.StreamRecord) { +func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuota() { + var err error ctx := context.Background() - streamRecordResp, err := s.Client.StreamRecord(ctx, &paymenttypes.QueryGetStreamRecordRequest{ - Account: addr, - }) - if streamRecordResp != nil { - s.Require().NoError(err) + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + // case: create bucket with zero read quota + bucketName := s.createBucket(user, 0) + + // bucket created + queryHeadBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + queryHeadBucketResponse, err := s.Client.HeadBucket(ctx, &queryHeadBucketRequest) + s.Require().NoError(err) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate, streamRecordsBefore.User.NetflowRate) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate, streamRecordsBefore.GVGFamily.NetflowRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate, streamRecordsBefore.Tax.NetflowRate) + + // case: create bucket with none zero read quota + bucketName = s.createBucket(user, 10240) + + // bucket created + queryHeadBucketRequest = storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + queryHeadBucketResponse, err = s.Client.HeadBucket(ctx, &queryHeadBucketRequest) + s.Require().NoError(err) + + // check price and rate calculation + queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: queryHeadBucketResponse.BucketInfo.CreateAt, + }) + s.T().Logf("queryGetSpStoragePriceByTimeResp %s, err: %v", queryGetSpStoragePriceByTimeResp, err) + s.Require().NoError(err) + + readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice + readChargeRate := readPrice.MulInt(sdk.NewIntFromUint64(queryHeadBucketResponse.BucketInfo.ChargedReadQuota)).TruncateInt() + s.T().Logf("readPrice: %s, readChargeRate: %s", readPrice, readChargeRate) + taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() + userTotalRate := readChargeRate.Add(taxRate) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), readChargeRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + + expectedOutFlows := []paymenttypes.OutFlow{ + {ToAddress: family.VirtualPaymentAddress, Rate: readChargeRate}, + {ToAddress: paymenttypes.ValidatorTaxPoolAddress.String(), Rate: taxRate}, + } + userOutFlowsResponse, err := s.Client.OutFlows(ctx, &paymenttypes.QueryOutFlowsRequest{Account: user.GetAddr().String()}) + s.Require().NoError(err) + sort.Slice(userOutFlowsResponse.OutFlows, func(i, j int) bool { + return userOutFlowsResponse.OutFlows[i].ToAddress < userOutFlowsResponse.OutFlows[j].ToAddress + }) + sort.Slice(expectedOutFlows, func(i, j int) bool { + return expectedOutFlows[i].ToAddress < expectedOutFlows[j].ToAddress + }) + s.Require().Equal(expectedOutFlows, userOutFlowsResponse.OutFlows) +} + +func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithZeroNoneZeroPayload() { + var err error + ctx := context.Background() + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + bucketName := s.createBucket(user, 0) + + // case: create object with zero payload size + streamRecordsBefore := s.getStreamRecords(streamAddresses) + _, _, objectName, _, _, payloadSize := s.createObject(user, bucketName, true) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) + gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + + // case: create object with none zero payload size + streamRecordsBefore = s.getStreamRecords(streamAddresses) + _, _, objectName, _, _, payloadSize = s.createObject(user, bucketName, false) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + lockFee := s.calculateLockFee(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.LockBalance.Sub(streamRecordsBefore.User.LockBalance), lockFee) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) +} + +func (s *PaymentTestSuite) TestStorageBill_CancelCreateObject() { + var err error + ctx := context.Background() + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + bucketName := s.createBucket(user, 0) + + // create object with none zero payload size + streamRecordsBefore := s.getStreamRecords(streamAddresses) + _, _, objectName, _, _, payloadSize := s.createObject(user, bucketName, false) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + lockFee := s.calculateLockFee(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.LockBalance.Sub(streamRecordsBefore.User.LockBalance), lockFee) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // cancel create object + s.cancelCreateObject(user, bucketName, objectName) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, lockFee) + s.Require().Equal(streamRecordsAfter.User.LockBalance.Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) +} + +func (s *PaymentTestSuite) TestStorageBill_SealObject_WithoutPriceChange() { + var err error + ctx := context.Background() + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + bucketName := s.createBucket(user, 0) + + // create object with none zero payload size + streamRecordsBefore := s.getStreamRecords(streamAddresses) + _, _, objectName, objectId, checksums, payloadSize := s.createObject(user, bucketName, false) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + lockFee := s.calculateLockFee(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.LockBalance.Sub(streamRecordsBefore.User.LockBalance), lockFee) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // case: seal object without price change + s.sealObject(bucketName, objectName, objectId, checksums) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) + gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) +} + +func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChange() { + var err error + ctx := context.Background() + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + bucketName := s.createBucket(user, 102400) + + // case: seal object with read price change and storage price change + _, _, objectName, objectId, checksums, payloadSize := s.createObject(user, bucketName, false) + + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: 0, + }) + s.Require().NoError(err) + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice.MulInt64(2), + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(2), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + streamRecordsBefore := s.getStreamRecords(streamAddresses) + gvgFamilyRateReadBefore, taxRateReadBefore, userTotalRateReadBefore := s.calculateReadRates(sp, bucketName) + s.sealObject(bucketName, objectName, objectId, checksums) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + gvgFamilyRateReadAfter, taxRateReadAfter, userTotalRateReadAfter := s.calculateReadRatesCurrentTimestamp(sp, bucketName) + gvgFamilyRateStore, gvgRateStore, taxRateStore, userTotalRateStore := s.calculateStorageRatesCurrentTimestamp(sp, bucketName, objectName, payloadSize) + + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) + + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRateReadAfter.Sub(userTotalRateReadBefore).Add(userTotalRateStore).Neg()) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRateStore) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRateReadAfter.Sub(gvgFamilyRateReadBefore).Add(gvgFamilyRateStore)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRateReadAfter.Sub(taxRateReadBefore).Add(taxRateStore)) +} + +func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { + var err error + ctx := context.Background() + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // full lifecycle + bucketName1 := s.createBucket(user, 0) + _, _, objectName1, _, _, _ := s.createObject(user, bucketName1, true) + _, _, objectName2, objectId2, checksums2, _ := s.createObject(user, bucketName1, false) + s.sealObject(bucketName1, objectName2, objectId2, checksums2) + + bucketName2 := s.createBucket(user, 1024) + _, _, objectName3, objectId3, checksums3, _ := s.createObject(user, bucketName2, false) + s.sealObject(bucketName2, objectName3, objectId3, checksums3) + _, _, objectName4, objectId4, checksums4, _ := s.createObject(user, bucketName2, false) + s.sealObject(bucketName2, objectName4, objectId4, checksums4) + + time.Sleep(3 * time.Second) + + s.deleteObject(user, bucketName1, objectName1) + s.deleteObject(user, bucketName1, objectName2) + s.deleteObject(user, bucketName2, objectName3) + s.deleteObject(user, bucketName2, objectName4) + err = s.deleteBucket(user, bucketName1) + s.Require().Error(err) + err = s.deleteBucket(user, bucketName2) + s.Require().Error(err) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().True(!streamRecordsAfter.User.StaticBalance.IsZero()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) +} + +func TestPaymentTestSuite(t *testing.T) { + suite.Run(t, new(PaymentTestSuite)) +} + +func (s *PaymentTestSuite) getStreamRecord(addr string) (sr paymenttypes.StreamRecord) { + ctx := context.Background() + streamRecordResp, err := s.Client.StreamRecord(ctx, &paymenttypes.QueryGetStreamRecordRequest{ + Account: addr, + }) + if streamRecordResp != nil { + s.Require().NoError(err) sr = streamRecordResp.StreamRecord } else { s.Require().ErrorContainsf(err, "not found", "account: %s", addr) @@ -1422,15 +1562,16 @@ func (s *PaymentTestSuite) GetStreamRecord(addr string) (sr paymenttypes.StreamR return sr } -func (s *PaymentTestSuite) GetStreamRecords(addrs []string) (streamRecords StreamRecords) { - streamRecords.User = s.GetStreamRecord(addrs[0]) - streamRecords.GVGFamily = s.GetStreamRecord(addrs[1]) - streamRecords.GVG = s.GetStreamRecord(addrs[2]) - streamRecords.Tax = s.GetStreamRecord(addrs[3]) +func (s *PaymentTestSuite) getStreamRecords(addrs []string) (streamRecords StreamRecords) { + streamRecords.User = s.getStreamRecord(addrs[0]) + streamRecords.GVGFamily = s.getStreamRecord(addrs[1]) + streamRecords.GVG = s.getStreamRecord(addrs[2]) + streamRecords.Tax = s.getStreamRecord(addrs[3]) + s.T().Logf("streamRecords: %s", core.YamlString(streamRecords)) return } -func (s *PaymentTestSuite) CheckStreamRecordsBeforeAndAfter(streamRecordsBefore StreamRecords, streamRecordsAfter StreamRecords, readPrice sdk.Dec, +func (s *PaymentTestSuite) checkStreamRecordsBeforeAndAfter(streamRecordsBefore StreamRecords, streamRecordsAfter StreamRecords, readPrice sdk.Dec, readChargeRate sdkmath.Int, primaryStorePrice sdk.Dec, secondaryStorePrice sdk.Dec, chargeSize uint64, payloadSize uint64) { userRateDiff := streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate) gvgFamilyRateDiff := streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate) @@ -1453,7 +1594,7 @@ func (s *PaymentTestSuite) CheckStreamRecordsBeforeAndAfter(streamRecordsBefore } } -func (s *PaymentTestSuite) GetChargeSize(payloadSize uint64) uint64 { +func (s *PaymentTestSuite) getChargeSize(payloadSize uint64) uint64 { ctx := context.Background() storageParams, err := s.Client.StorageQueryClient.Params(ctx, &storagetypes.QueryParamsRequest{}) s.Require().NoError(err) @@ -1466,6 +1607,431 @@ func (s *PaymentTestSuite) GetChargeSize(payloadSize uint64) uint64 { } } -func TestPaymentTestSuite(t *testing.T) { - suite.Run(t, new(PaymentTestSuite)) +func (s *PaymentTestSuite) calculateLockFee(sp core.StorageProvider, bucketName, objectName string, payloadSize uint64) sdkmath.Int { + ctx := context.Background() + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + //queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + // BucketName: bucketName, + // ObjectName: objectName, + //} + //headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) + //s.Require().NoError(err) + + //s.Client.GlobalVirtualGroup(ctx, virtualgrouptypes.QueryGlobalVirtualGroupRequest{GlobalVirtualGroupId: headObjectResponse.ObjectInfo.}) + //gvgCount := len(headObjectResponse.GlobalVirtualGroup.SecondarySpIds) + gvgCount := 6 + + headBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + headBucketResponse, err := s.Client.HeadBucket(ctx, &headBucketRequest) + s.Require().NoError(err) + + chargeSize := int64(s.getChargeSize(payloadSize)) + _, primaryPrice, secondaryPrice := s.getPrices(sp, headBucketResponse.BucketInfo.CreateAt) + + gvgFamilyRate := primaryPrice.MulInt64(chargeSize).TruncateInt() + gvgRate := secondaryPrice.MulInt64(chargeSize * int64(gvgCount)).TruncateInt() + taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() + return gvgFamilyRate.Add(gvgRate).Add(taxRate).MulRaw(int64(paymentParams.Params.VersionedParams.ReserveTime)) +} + +func (s *PaymentTestSuite) getPrices(sp core.StorageProvider, timestamp int64) (sdk.Dec, sdk.Dec, sdk.Dec) { + ctx := context.Background() + + spStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: timestamp, + }) + s.T().Logf("spStoragePriceByTimeResp %s, err: %v", spStoragePriceByTimeResp, err) + s.Require().NoError(err) + + secondaryStoragePriceByTimeResp, err := s.Client.QueryGetSecondarySpStorePriceByTime(ctx, &sptypes.QueryGetSecondarySpStorePriceByTimeRequest{ + Timestamp: timestamp, + }) + s.T().Logf("spStoragePriceByTimeResp %s, err: %v", spStoragePriceByTimeResp, err) + s.Require().NoError(err) + + return spStoragePriceByTimeResp.SpStoragePrice.ReadPrice, spStoragePriceByTimeResp.SpStoragePrice.StorePrice, + secondaryStoragePriceByTimeResp.SecondarySpStorePrice.StorePrice +} + +func (s *PaymentTestSuite) calculateReadRates(sp core.StorageProvider, bucketName string) (sdkmath.Int, sdkmath.Int, sdkmath.Int) { + ctx := context.Background() + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + headBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + headBucketResponse, err := s.Client.HeadBucket(ctx, &headBucketRequest) + s.Require().NoError(err) + + readPrice, _, _ := s.getPrices(sp, headBucketResponse.BucketInfo.CreateAt) + + gvgFamilyRate := readPrice.MulInt64(int64(headBucketResponse.BucketInfo.ChargedReadQuota)).TruncateInt() + taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate).TruncateInt() + return gvgFamilyRate, taxRate, gvgFamilyRate.Add(taxRate) +} + +func (s *PaymentTestSuite) calculateReadRatesCurrentTimestamp(sp core.StorageProvider, bucketName string) (sdkmath.Int, sdkmath.Int, sdkmath.Int) { + ctx := context.Background() + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + headBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + headBucketResponse, err := s.Client.HeadBucket(ctx, &headBucketRequest) + s.Require().NoError(err) + + readPrice, _, _ := s.getPrices(sp, time.Now().Unix()) + + gvgFamilyRate := readPrice.MulInt64(int64(headBucketResponse.BucketInfo.ChargedReadQuota)).TruncateInt() + taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate).TruncateInt() + return gvgFamilyRate, taxRate, gvgFamilyRate.Add(taxRate) +} + +func (s *PaymentTestSuite) calculateStorageRates(sp core.StorageProvider, bucketName, objectName string, payloadSize uint64) (sdkmath.Int, sdkmath.Int, sdkmath.Int, sdkmath.Int) { + ctx := context.Background() + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName, + } + headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) + s.Require().NoError(err) + gvgCount := len(headObjectResponse.GlobalVirtualGroup.SecondarySpIds) + + headBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + headBucketResponse, err := s.Client.HeadBucket(ctx, &headBucketRequest) + s.Require().NoError(err) + + chargeSize := int64(s.getChargeSize(payloadSize)) + _, primaryPrice, secondaryPrice := s.getPrices(sp, headBucketResponse.BucketInfo.CreateAt) + + gvgFamilyRate := primaryPrice.MulInt64(chargeSize).TruncateInt() + gvgRate := secondaryPrice.MulInt64(chargeSize * int64(gvgCount)).TruncateInt() + taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() + return gvgFamilyRate, gvgRate, taxRate, gvgFamilyRate.Add(gvgRate).Add(taxRate) +} + +func (s *PaymentTestSuite) calculateStorageRatesCurrentTimestamp(sp core.StorageProvider, bucketName, objectName string, payloadSize uint64) (sdkmath.Int, sdkmath.Int, sdkmath.Int, sdkmath.Int) { + ctx := context.Background() + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName, + } + headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) + s.Require().NoError(err) + gvgCount := len(headObjectResponse.GlobalVirtualGroup.SecondarySpIds) + + chargeSize := int64(s.getChargeSize(payloadSize)) + _, primaryPrice, secondaryPrice := s.getPrices(sp, time.Now().Unix()) + + gvgFamilyRate := primaryPrice.MulInt64(chargeSize).TruncateInt() + gvgRate := secondaryPrice.MulInt64(chargeSize * int64(gvgCount)).TruncateInt() + taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() + return gvgFamilyRate, gvgRate, taxRate, gvgFamilyRate.Add(gvgRate).Add(taxRate) +} + +func (s *PaymentTestSuite) updateParams(params paymenttypes.Params) { + var err error + validator := s.Validator.GetAddr() + + ctx := context.Background() + + ts := time.Now().Unix() + queryParamsRequest := &paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, queryParamsRequest) + s.Require().NoError(err) + + msgUpdateParams := &paymenttypes.MsgUpdateParams{ + Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), + Params: params, + } + + msgProposal, err := govtypesv1.NewMsgSubmitProposal( + []sdk.Msg{msgUpdateParams}, + sdk.Coins{sdk.NewCoin(s.BaseSuite.Config.Denom, types.NewIntFromInt64WithDecimal(100, types.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) + + queryParamsByTimestampRequest := &paymenttypes.QueryParamsByTimestampRequest{Timestamp: ts} + queryParamsByTimestampResponse, err := s.Client.PaymentQueryClient.ParamsByTimestamp(ctx, queryParamsByTimestampRequest) + s.Require().NoError(err) + s.Require().Equal(queryParamsResponse.Params.VersionedParams.ReserveTime, + queryParamsByTimestampResponse.Params.VersionedParams.ReserveTime) + s.T().Logf("new params: %s", params.String()) +} + +func (s *PaymentTestSuite) createBucketAndObject() (keys.KeyManager, string, string, storagetypes.Uint, [][]byte) { + var err error + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + + // CreateBucket + user := s.GenAndChargeAccounts(1, 1000000)[0] + bucketName := "ch" + storagetestutils.GenRandomBucketName() + msgCreateBucket := storagetypes.NewMsgCreateBucket( + user.GetAddr(), bucketName, storagetypes.VISIBILITY_TYPE_PRIVATE, 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) + + // CreateObject + objectName := storagetestutils.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(context.Background(), &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectName, objectName) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.BucketName, bucketName) + + return user, bucketName, objectName, queryHeadObjectResponse.ObjectInfo.Id, expectChecksum +} + +func (s *PaymentTestSuite) createBucket(user keys.KeyManager, readQuota uint64) string { + var err error + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + + // CreateBucket + bucketName := "ch" + storagetestutils.GenRandomBucketName() + msgCreateBucket := storagetypes.NewMsgCreateBucket( + user.GetAddr(), bucketName, storagetypes.VISIBILITY_TYPE_PRIVATE, sp.OperatorKey.GetAddr(), + nil, math.MaxUint, nil, readQuota) + msgCreateBucket.PrimarySpApproval.GlobalVirtualGroupFamilyId = gvg.FamilyId + msgCreateBucket.PrimarySpApproval.Sig, err = sp.ApprovalKey.Sign(msgCreateBucket.GetApprovalBytes()) + s.Require().NoError(err) + s.SendTxBlock(user, msgCreateBucket) + + queryHeadBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + _, err = s.Client.HeadBucket(context.Background(), &queryHeadBucketRequest) + s.Require().NoError(err) + + return bucketName +} + +func (s *PaymentTestSuite) createObject(user keys.KeyManager, bucketName string, empty bool) (keys.KeyManager, string, string, storagetypes.Uint, [][]byte, uint64) { + var err error + sp := s.StorageProviders[0] + + // CreateObject + objectName := storagetestutils.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. + if !empty { + for i := 0; i < 1024; i++ { + buffer.WriteString(fmt.Sprintf("[%05d] %s\n", i, line)) + } + } + payloadSize := uint64(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, 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, + } + headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(headObjectResponse.ObjectInfo.ObjectName, objectName) + s.Require().Equal(headObjectResponse.ObjectInfo.BucketName, bucketName) + + return user, bucketName, objectName, headObjectResponse.ObjectInfo.Id, expectChecksum, payloadSize +} + +func (s *PaymentTestSuite) cancelCreateObject(user keys.KeyManager, bucketName, objectName string) { + msgCancelCreateObject := storagetypes.NewMsgCancelCreateObject(user.GetAddr(), bucketName, objectName) + s.SendTxBlock(user, msgCancelCreateObject) + + // HeadObject + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName, + } + _, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) + s.Require().Error(err) +} + +func (s *PaymentTestSuite) sealObject(bucketName, objectName string, objectId storagetypes.Uint, checksums [][]byte) *virtualgrouptypes.GlobalVirtualGroup { + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + s.T().Log("GVG info: ", gvg.String()) + + // SealObject + gvgId := gvg.Id + msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvg.Id, nil) + secondarySigs := make([][]byte, 0) + secondarySPBlsPubKeys := make([]bls.PublicKey, 0) + blsSignHash := storagetypes.NewSecondarySpSealObjectSignDoc(s.GetChainID(), gvgId, objectId, storagetypes.GenerateHash(checksums[:])).GetBlsSignHash() + // every secondary sp signs the checksums + for i := 1; i < len(s.StorageProviders); i++ { + sig, err := core.BlsSignAndVerify(s.StorageProviders[i], blsSignHash) + s.Require().NoError(err) + secondarySigs = append(secondarySigs, sig) + pk, err := bls.PublicKeyFromBytes(s.StorageProviders[i].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) + + queryHeadObjectRequest2 := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName, + } + queryHeadObjectResponse2, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest2) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse2.ObjectInfo.ObjectName, objectName) + s.Require().Equal(queryHeadObjectResponse2.ObjectInfo.BucketName, bucketName) + s.Require().Equal(queryHeadObjectResponse2.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + + return gvg +} + +func (s *PaymentTestSuite) deleteObject(user keys.KeyManager, bucketName, objectName string) error { + msgDeleteObject := storagetypes.NewMsgDeleteObject(user.GetAddr(), bucketName, objectName) + s.SendTxBlock(user, msgDeleteObject) + + // HeadObject + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName, + } + _, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) + return err +} + +func (s *PaymentTestSuite) deleteBucket(user keys.KeyManager, bucketName string) error { + msgDeleteObject := storagetypes.NewMsgDeleteBucket(user.GetAddr(), bucketName) + s.SendTxBlock(user, msgDeleteObject) + + // HeadObject + queryHeadBucektRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + _, err := s.Client.HeadBucket(context.Background(), &queryHeadBucektRequest) + return err } diff --git a/x/storage/keeper/payment.go b/x/storage/keeper/payment.go index 637e62fcf..a33b5eb0f 100644 --- a/x/storage/keeper/payment.go +++ b/x/storage/keeper/payment.go @@ -219,46 +219,19 @@ func (k Keeper) UnChargeObjectStoreFee(ctx sdk.Context, bucketInfo *storagetypes return fmt.Errorf("get charge size error: %w", err) } - priceChanged, err := k.IsPriceChanged(ctx, bucketInfo.PrimarySpId, internalBucketInfo.PriceTime) + err = k.ChargeViaObjectChange(ctx, bucketInfo, internalBucketInfo, objectInfo, chargeSize, true) if err != nil { - return fmt.Errorf("check whether price changed error: %w", err) - } - - oldInternalBucketInfo := &storagetypes.InternalBucketInfo{ - PriceTime: internalBucketInfo.PriceTime, - TotalChargeSize: internalBucketInfo.TotalChargeSize, - LocalVirtualGroups: internalBucketInfo.LocalVirtualGroups, - } - - if !priceChanged { - err = k.ChargeViaObjectChange(ctx, bucketInfo, internalBucketInfo, objectInfo, chargeSize, true) - if err != nil { - return fmt.Errorf("apply object store bill error: %w", err) - } - } else { - err = k.ChargeViaBucketChange(ctx, bucketInfo, internalBucketInfo, func(bi *storagetypes.BucketInfo, ibi *storagetypes.InternalBucketInfo) error { - ibi.TotalChargeSize -= chargeSize - for _, lvg := range ibi.LocalVirtualGroups { - if lvg.Id == objectInfo.LocalVirtualGroupId { - lvg.TotalChargeSize -= chargeSize - break - } - } - return nil - }) - if err != nil { - return fmt.Errorf("apply object store bill error: %w", err) - } + return fmt.Errorf("apply object store bill error: %w", err) } blockTime := ctx.BlockTime().Unix() - versionParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, oldInternalBucketInfo.PriceTime) + versionParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, internalBucketInfo.PriceTime) if err != nil { return fmt.Errorf("failed to get versioned params: %w", err) } timeToPay := objectInfo.CreateAt + int64(versionParams.ReserveTime) - blockTime if timeToPay > 0 { // store less than reserve time - err = k.ChargeObjectStoreFeeForEarlyDeletion(ctx, bucketInfo, oldInternalBucketInfo, objectInfo, chargeSize, timeToPay) + err = k.ChargeObjectStoreFeeForEarlyDeletion(ctx, bucketInfo, internalBucketInfo, objectInfo, chargeSize, timeToPay) forced, _ := ctx.Value(types.ForceUpdateStreamRecordKey).(bool) // force update in end block if !forced && err != nil { return fmt.Errorf("fail to pay for early deletion, error: %w", err) @@ -598,6 +571,7 @@ func (k Keeper) GetObjectLockFee(ctx sdk.Context, primarySpId uint32, priceTime if err != nil { return amount, fmt.Errorf("get versioned reserve time error: %w", err) } + rate = versionedParams.ValidatorTaxRate.MulInt(rate).TruncateInt().Add(rate) // should also lock for validator tax pool amount = rate.Mul(sdkmath.NewIntFromUint64(versionedParams.ReserveTime)) return amount, nil } diff --git a/x/storage/keeper/payment_test.go b/x/storage/keeper/payment_test.go index 477aac26c..4499e016b 100644 --- a/x/storage/keeper/payment_test.go +++ b/x/storage/keeper/payment_test.go @@ -127,7 +127,7 @@ func (s *TestSuite) TestGetObjectLockFee() { s.Require().True(amount.Equal(expectedAmount)) } -func (s *TestSuite) TestGetBucketBill() { +func (s *TestSuite) TestGetBucketReadBill() { gvgFamily := &virtualgroupmoduletypes.GlobalVirtualGroupFamily{ Id: 1, VirtualPaymentAddress: sample.RandAccAddress().String(), @@ -188,9 +188,37 @@ func (s *TestSuite) TestGetBucketBill() { taxPoolRate := params.VersionedParams.ValidatorTaxRate.MulInt(readRate).TruncateInt() s.Require().Equal(flows.Flows[1].ToAddress, paymenttypes.ValidatorTaxPoolAddress.String()) s.Require().Equal(flows.Flows[1].Rate, taxPoolRate) +} + +func (s *TestSuite) TestGetBucketReadStoreBill() { + gvgFamily := &virtualgroupmoduletypes.GlobalVirtualGroupFamily{ + Id: 1, + VirtualPaymentAddress: sample.RandAccAddress().String(), + } + s.virtualGroupKeeper.EXPECT().GetGVGFamily(gomock.Any(), gomock.Any(), gomock.Any()). + Return(gvgFamily, true).AnyTimes() + + primarySp := &sptypes.StorageProvider{ + Status: sptypes.STATUS_IN_SERVICE, + Id: 100, + OperatorAddress: sample.RandAccAddress().String(), + FundingAddress: sample.RandAccAddress().String()} + s.spKeeper.EXPECT().GetStorageProvider(gomock.Any(), gomock.Eq(primarySp.Id)). + Return(primarySp, true).AnyTimes() + + price := paymenttypes.StoragePrice{ + ReadPrice: sdk.NewDec(100), + PrimaryStorePrice: sdk.NewDec(1000), + SecondaryStorePrice: sdk.NewDec(500), + } + s.paymentKeeper.EXPECT().GetStoragePrice(gomock.Any(), gomock.Any()). + Return(price, nil).AnyTimes() + params := paymenttypes.DefaultParams() + s.paymentKeeper.EXPECT().GetVersionedParamsWithTs(gomock.Any(), gomock.Any()). + Return(params.VersionedParams, nil).AnyTimes() // none empty bucket - bucketInfo = &types.BucketInfo{ + bucketInfo := &types.BucketInfo{ Owner: "", BucketName: "bucketname", Id: sdk.NewUint(1), @@ -200,7 +228,7 @@ func (s *TestSuite) TestGetBucketBill() { ChargedReadQuota: 100, } - internalBucketInfo = &types.InternalBucketInfo{ + internalBucketInfo := &types.InternalBucketInfo{ TotalChargeSize: 300, LocalVirtualGroups: []*types.LocalVirtualGroup{ { @@ -232,7 +260,7 @@ func (s *TestSuite) TestGetBucketBill() { s.virtualGroupKeeper.EXPECT().GetGVG(gomock.Any(), gvg2.Id). Return(gvg2, true).AnyTimes() - flows, err = s.storageKeeper.GetBucketReadStoreBill(s.ctx, bucketInfo, internalBucketInfo) + flows, err := s.storageKeeper.GetBucketReadStoreBill(s.ctx, bucketInfo, internalBucketInfo) s.Require().NoError(err) gvg1StoreSize := internalBucketInfo.LocalVirtualGroups[0].TotalChargeSize * uint64(len(gvg1.SecondarySpIds)) @@ -245,13 +273,13 @@ func (s *TestSuite) TestGetBucketBill() { s.Require().Equal(flows.Flows[1].ToAddress, gvg2.VirtualPaymentAddress) s.Require().Equal(flows.Flows[1].Rate, gvg2StoreRate) - readRate = price.ReadPrice.MulInt64(int64(bucketInfo.ChargedReadQuota)).TruncateInt() + readRate := price.ReadPrice.MulInt64(int64(bucketInfo.ChargedReadQuota)).TruncateInt() primaryStoreRate := price.PrimaryStorePrice.MulInt64(int64(internalBucketInfo.TotalChargeSize)).TruncateInt() s.Require().Equal(flows.Flows[2].ToAddress, gvgFamily.VirtualPaymentAddress) s.Require().Equal(flows.Flows[2].Rate, readRate.Add(primaryStoreRate)) totalRate := readRate.Add(primaryStoreRate).Add(gvg1StoreRate).Add(gvg2StoreRate) - taxPoolRate = params.VersionedParams.ValidatorTaxRate.MulInt(totalRate).TruncateInt() + taxPoolRate := params.VersionedParams.ValidatorTaxRate.MulInt(totalRate).TruncateInt() s.Require().Equal(flows.Flows[3].ToAddress, paymenttypes.ValidatorTaxPoolAddress.String()) s.Require().Equal(flows.Flows[3].Rate, taxPoolRate) } From 9f8c7df48c31b04030b37a6eedb7bf8c09679a99 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Fri, 14 Jul 2023 13:41:10 +0800 Subject: [PATCH 03/33] add some query apis --- e2e/tests/payment_test.go | 24 +- proto/greenfield/storage/query.proto | 55 + x/storage/keeper/grpc_query.go | 44 + x/storage/keeper/payment.go | 19 +- x/storage/types/query.pb.go | 1429 ++++++++++++++++++++++---- x/storage/types/query.pb.gw.go | 202 ++++ 6 files changed, 1564 insertions(+), 209 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index e4d4900a8..de8e2fbf4 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -1614,28 +1614,19 @@ func (s *PaymentTestSuite) calculateLockFee(sp core.StorageProvider, bucketName, s.T().Logf("paymentParams %s, err: %v", paymentParams, err) s.Require().NoError(err) - //queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ - // BucketName: bucketName, - // ObjectName: objectName, - //} - //headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) - //s.Require().NoError(err) - - //s.Client.GlobalVirtualGroup(ctx, virtualgrouptypes.QueryGlobalVirtualGroupRequest{GlobalVirtualGroupId: headObjectResponse.ObjectInfo.}) - //gvgCount := len(headObjectResponse.GlobalVirtualGroup.SecondarySpIds) - gvgCount := 6 + headBucketExtraResponse, err := s.Client.HeadBucketExtra(ctx, &storagetypes.QueryHeadBucketExtraRequest{BucketName: bucketName}) + s.Require().NoError(err) - headBucketRequest := storagetypes.QueryHeadBucketRequest{ - BucketName: bucketName, - } - headBucketResponse, err := s.Client.HeadBucket(ctx, &headBucketRequest) + storageParams, err := s.Client.StorageQueryClient.Params(ctx, &storagetypes.QueryParamsRequest{}) + s.T().Logf("storageParams %s, err: %v", storageParams, err) s.Require().NoError(err) + secondarySpCount := storageParams.Params.VersionedParams.RedundantDataChunkNum + storageParams.Params.VersionedParams.RedundantParityChunkNum chargeSize := int64(s.getChargeSize(payloadSize)) - _, primaryPrice, secondaryPrice := s.getPrices(sp, headBucketResponse.BucketInfo.CreateAt) + _, primaryPrice, secondaryPrice := s.getPrices(sp, headBucketExtraResponse.ExtraInfo.PriceTime) gvgFamilyRate := primaryPrice.MulInt64(chargeSize).TruncateInt() - gvgRate := secondaryPrice.MulInt64(chargeSize * int64(gvgCount)).TruncateInt() + gvgRate := secondaryPrice.MulInt64(chargeSize * int64(secondarySpCount)).TruncateInt() taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() return gvgFamilyRate.Add(gvgRate).Add(taxRate).MulRaw(int64(paymentParams.Params.VersionedParams.ReserveTime)) } @@ -1714,6 +1705,7 @@ func (s *PaymentTestSuite) calculateStorageRates(sp core.StorageProvider, bucket headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) s.Require().NoError(err) gvgCount := len(headObjectResponse.GlobalVirtualGroup.SecondarySpIds) + fmt.Println("gvgCount", gvgCount) headBucketRequest := storagetypes.QueryHeadBucketRequest{ BucketName: bucketName, diff --git a/proto/greenfield/storage/query.proto b/proto/greenfield/storage/query.proto index ad2bb14eb..467233a64 100644 --- a/proto/greenfield/storage/query.proto +++ b/proto/greenfield/storage/query.proto @@ -118,6 +118,16 @@ service Query { option (google.api.http).get = "/greenfield/storage/lock_fee"; } + // Queries a bucket extra info (with gvg bindings and price time) with specify name. + rpc HeadBucketExtra(QueryHeadBucketExtraRequest) returns (QueryHeadBucketExtraResponse) { + option (google.api.http).get = "/greenfield/storage/head_bucket_extra/{bucket_name}"; + } + + // Queries whether read and storage prices changed for the bucket. + rpc QueryIsPriceChanged(QueryIsPriceChangedRequest) returns (QueryIsPriceChangedResponse) { + option (google.api.http).get = "/greenfield/storage/is_price_changed/{bucket_name}"; + } + // this line is used by starport scaffolding # 2 } @@ -291,4 +301,49 @@ message QueryLockFeeResponse { ]; } +message QueryHeadBucketExtraRequest { + string bucket_name = 1; +} + +message QueryHeadBucketExtraResponse { + InternalBucketInfo extra_info = 1; +} + +message QueryIsPriceChangedRequest { + string bucket_name = 1; +} + +message QueryIsPriceChangedResponse { + bool changed = 1; + string current_read_price = 2 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string current_primary_store_price = 3 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string current_secondary_store_price = 4 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string new_read_price = 5 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string new_primary_store_price = 6 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string new_secondary_store_price = 7 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; +} // this line is used by starport scaffolding # 3 diff --git a/x/storage/keeper/grpc_query.go b/x/storage/keeper/grpc_query.go index 6e9972a20..9f63bb56b 100644 --- a/x/storage/keeper/grpc_query.go +++ b/x/storage/keeper/grpc_query.go @@ -71,3 +71,47 @@ func (k Keeper) QueryLockFee(c context.Context, req *types.QueryLockFeeRequest) return &types.QueryLockFeeResponse{Amount: amount}, nil } + +func (k Keeper) HeadBucketExtra(c context.Context, req *types.QueryHeadBucketExtraRequest) (*types.QueryHeadBucketExtraResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + ctx := sdk.UnwrapSDKContext(c) + bucketInfo, found := k.GetBucketInfo(ctx, req.BucketName) + if !found { + return nil, types.ErrNoSuchBucket + } + + internalBucketInfo := k.MustGetInternalBucketInfo(ctx, bucketInfo.Id) + + return &types.QueryHeadBucketExtraResponse{ + ExtraInfo: internalBucketInfo, + }, nil +} + +func (k Keeper) QueryIsPriceChanged(c context.Context, req *types.QueryIsPriceChangedRequest) (*types.QueryIsPriceChangedResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + ctx := sdk.UnwrapSDKContext(c) + bucketInfo, found := k.GetBucketInfo(ctx, req.BucketName) + if !found { + return nil, types.ErrNoSuchBucket + } + + internalBucketInfo := k.MustGetInternalBucketInfo(ctx, bucketInfo.Id) + changed, currentRead, currentPrimary, currentSecondary, newRead, newPrimary, newSecondary, err := k.IsPriceChanged(ctx, bucketInfo.PrimarySpId, internalBucketInfo.PriceTime) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryIsPriceChangedResponse{ + Changed: changed, + CurrentReadPrice: currentRead, + CurrentPrimaryStorePrice: currentPrimary, + CurrentSecondaryStorePrice: currentSecondary, + NewReadPrice: newRead, + NewPrimaryStorePrice: newPrimary, + NewSecondaryStorePrice: newSecondary, + }, nil +} diff --git a/x/storage/keeper/payment.go b/x/storage/keeper/payment.go index a33b5eb0f..69eb39670 100644 --- a/x/storage/keeper/payment.go +++ b/x/storage/keeper/payment.go @@ -159,25 +159,32 @@ func (k Keeper) UnlockAndChargeObjectStoreFee(ctx sdk.Context, bucketInfo *stora return k.ChargeObjectStoreFee(ctx, bucketInfo, internalBucketInfo, objectInfo) } -func (k Keeper) IsPriceChanged(ctx sdk.Context, primarySpId uint32, priceTime int64) (bool, error) { +func (k Keeper) IsPriceChanged(ctx sdk.Context, primarySpId uint32, priceTime int64) (bool, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, error) { prePrice, err := k.paymentKeeper.GetStoragePrice(ctx, types.StoragePriceParams{ PrimarySp: primarySpId, PriceTime: priceTime, }) if err != nil { - return false, fmt.Errorf("get storage price failed: %w", err) + return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get storage price failed: %w", err) } currentPrice, err := k.paymentKeeper.GetStoragePrice(ctx, types.StoragePriceParams{ PrimarySp: primarySpId, PriceTime: ctx.BlockTime().Unix(), }) if err != nil { - return false, fmt.Errorf("get storage price failed: %w", err) + return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get storage price failed: %w", err) } return !(prePrice.ReadPrice.Equal(currentPrice.ReadPrice) && - prePrice.PrimaryStorePrice.Equal(currentPrice.PrimaryStorePrice) && - prePrice.SecondaryStorePrice.Equal(currentPrice.SecondaryStorePrice)), nil + prePrice.PrimaryStorePrice.Equal(currentPrice.PrimaryStorePrice) && + prePrice.SecondaryStorePrice.Equal(currentPrice.SecondaryStorePrice)), + prePrice.ReadPrice, + prePrice.PrimaryStorePrice, + prePrice.SecondaryStorePrice, + currentPrice.ReadPrice, + currentPrice.PrimaryStorePrice, + currentPrice.SecondaryStorePrice, + nil } func (k Keeper) ChargeObjectStoreFee(ctx sdk.Context, bucketInfo *storagetypes.BucketInfo, @@ -187,7 +194,7 @@ func (k Keeper) ChargeObjectStoreFee(ctx sdk.Context, bucketInfo *storagetypes.B return fmt.Errorf("get charge size error: %w", err) } - priceChanged, err := k.IsPriceChanged(ctx, bucketInfo.PrimarySpId, internalBucketInfo.PriceTime) + priceChanged, _, _, _, _, _, _, err := k.IsPriceChanged(ctx, bucketInfo.PrimarySpId, internalBucketInfo.PriceTime) if err != nil { return fmt.Errorf("check whether price changed error: %w", err) } diff --git a/x/storage/types/query.pb.go b/x/storage/types/query.pb.go index ee814f80c..b6f5667a0 100644 --- a/x/storage/types/query.pb.go +++ b/x/storage/types/query.pb.go @@ -1713,6 +1713,188 @@ func (m *QueryLockFeeResponse) XXX_DiscardUnknown() { var xxx_messageInfo_QueryLockFeeResponse proto.InternalMessageInfo +type QueryHeadBucketExtraRequest struct { + BucketName string `protobuf:"bytes,1,opt,name=bucket_name,json=bucketName,proto3" json:"bucket_name,omitempty"` +} + +func (m *QueryHeadBucketExtraRequest) Reset() { *m = QueryHeadBucketExtraRequest{} } +func (m *QueryHeadBucketExtraRequest) String() string { return proto.CompactTextString(m) } +func (*QueryHeadBucketExtraRequest) ProtoMessage() {} +func (*QueryHeadBucketExtraRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_b1b80b580af04cb0, []int{35} +} +func (m *QueryHeadBucketExtraRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryHeadBucketExtraRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryHeadBucketExtraRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryHeadBucketExtraRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryHeadBucketExtraRequest.Merge(m, src) +} +func (m *QueryHeadBucketExtraRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryHeadBucketExtraRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryHeadBucketExtraRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryHeadBucketExtraRequest proto.InternalMessageInfo + +func (m *QueryHeadBucketExtraRequest) GetBucketName() string { + if m != nil { + return m.BucketName + } + return "" +} + +type QueryHeadBucketExtraResponse struct { + ExtraInfo *InternalBucketInfo `protobuf:"bytes,1,opt,name=extra_info,json=extraInfo,proto3" json:"extra_info,omitempty"` +} + +func (m *QueryHeadBucketExtraResponse) Reset() { *m = QueryHeadBucketExtraResponse{} } +func (m *QueryHeadBucketExtraResponse) String() string { return proto.CompactTextString(m) } +func (*QueryHeadBucketExtraResponse) ProtoMessage() {} +func (*QueryHeadBucketExtraResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b1b80b580af04cb0, []int{36} +} +func (m *QueryHeadBucketExtraResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryHeadBucketExtraResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryHeadBucketExtraResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryHeadBucketExtraResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryHeadBucketExtraResponse.Merge(m, src) +} +func (m *QueryHeadBucketExtraResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryHeadBucketExtraResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryHeadBucketExtraResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryHeadBucketExtraResponse proto.InternalMessageInfo + +func (m *QueryHeadBucketExtraResponse) GetExtraInfo() *InternalBucketInfo { + if m != nil { + return m.ExtraInfo + } + return nil +} + +type QueryIsPriceChangedRequest struct { + BucketName string `protobuf:"bytes,1,opt,name=bucket_name,json=bucketName,proto3" json:"bucket_name,omitempty"` +} + +func (m *QueryIsPriceChangedRequest) Reset() { *m = QueryIsPriceChangedRequest{} } +func (m *QueryIsPriceChangedRequest) String() string { return proto.CompactTextString(m) } +func (*QueryIsPriceChangedRequest) ProtoMessage() {} +func (*QueryIsPriceChangedRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_b1b80b580af04cb0, []int{37} +} +func (m *QueryIsPriceChangedRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryIsPriceChangedRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryIsPriceChangedRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryIsPriceChangedRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryIsPriceChangedRequest.Merge(m, src) +} +func (m *QueryIsPriceChangedRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryIsPriceChangedRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryIsPriceChangedRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryIsPriceChangedRequest proto.InternalMessageInfo + +func (m *QueryIsPriceChangedRequest) GetBucketName() string { + if m != nil { + return m.BucketName + } + return "" +} + +type QueryIsPriceChangedResponse struct { + Changed bool `protobuf:"varint,1,opt,name=changed,proto3" json:"changed,omitempty"` + CurrentReadPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=current_read_price,json=currentReadPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"current_read_price"` + CurrentPrimaryStorePrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=current_primary_store_price,json=currentPrimaryStorePrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"current_primary_store_price"` + CurrentSecondaryStorePrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=current_secondary_store_price,json=currentSecondaryStorePrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"current_secondary_store_price"` + NewReadPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=new_read_price,json=newReadPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"new_read_price"` + NewPrimaryStorePrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=new_primary_store_price,json=newPrimaryStorePrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"new_primary_store_price"` + NewSecondaryStorePrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=new_secondary_store_price,json=newSecondaryStorePrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"new_secondary_store_price"` +} + +func (m *QueryIsPriceChangedResponse) Reset() { *m = QueryIsPriceChangedResponse{} } +func (m *QueryIsPriceChangedResponse) String() string { return proto.CompactTextString(m) } +func (*QueryIsPriceChangedResponse) ProtoMessage() {} +func (*QueryIsPriceChangedResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b1b80b580af04cb0, []int{38} +} +func (m *QueryIsPriceChangedResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryIsPriceChangedResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryIsPriceChangedResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryIsPriceChangedResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryIsPriceChangedResponse.Merge(m, src) +} +func (m *QueryIsPriceChangedResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryIsPriceChangedResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryIsPriceChangedResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryIsPriceChangedResponse proto.InternalMessageInfo + +func (m *QueryIsPriceChangedResponse) GetChanged() bool { + if m != nil { + return m.Changed + } + return false +} + func init() { proto.RegisterType((*QueryParamsRequest)(nil), "greenfield.storage.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "greenfield.storage.QueryParamsResponse") @@ -1749,135 +1931,157 @@ func init() { proto.RegisterType((*QueryPolicyByIdResponse)(nil), "greenfield.storage.QueryPolicyByIdResponse") proto.RegisterType((*QueryLockFeeRequest)(nil), "greenfield.storage.QueryLockFeeRequest") proto.RegisterType((*QueryLockFeeResponse)(nil), "greenfield.storage.QueryLockFeeResponse") + proto.RegisterType((*QueryHeadBucketExtraRequest)(nil), "greenfield.storage.QueryHeadBucketExtraRequest") + proto.RegisterType((*QueryHeadBucketExtraResponse)(nil), "greenfield.storage.QueryHeadBucketExtraResponse") + proto.RegisterType((*QueryIsPriceChangedRequest)(nil), "greenfield.storage.QueryIsPriceChangedRequest") + proto.RegisterType((*QueryIsPriceChangedResponse)(nil), "greenfield.storage.QueryIsPriceChangedResponse") } func init() { proto.RegisterFile("greenfield/storage/query.proto", fileDescriptor_b1b80b580af04cb0) } var fileDescriptor_b1b80b580af04cb0 = []byte{ - // 1956 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x59, 0xcd, 0x8f, 0x1c, 0x47, - 0x15, 0x77, 0xef, 0x9a, 0x65, 0xb7, 0x66, 0xb1, 0x43, 0xb1, 0x01, 0xa7, 0xb3, 0x1e, 0xdb, 0x1d, - 0xb0, 0x37, 0x8e, 0x77, 0xda, 0xeb, 0xc4, 0x88, 0x55, 0x3e, 0xd0, 0x0e, 0xf1, 0x2e, 0x23, 0xf9, - 0x8b, 0xf1, 0xca, 0x88, 0x95, 0x50, 0xab, 0xa6, 0xbb, 0x66, 0xdc, 0xec, 0x74, 0x57, 0xbb, 0xbb, - 0xc7, 0x30, 0x19, 0xcd, 0x81, 0x5c, 0xe0, 0x88, 0x40, 0x48, 0x11, 0x22, 0x12, 0x08, 0x81, 0x80, - 0x0b, 0x97, 0x5c, 0x38, 0x71, 0xe1, 0x10, 0x09, 0x21, 0x45, 0xe1, 0x82, 0x72, 0x88, 0x90, 0xcd, - 0x1f, 0x12, 0x75, 0xd5, 0xeb, 0xee, 0xea, 0xaf, 0xe9, 0xd9, 0xec, 0x9e, 0x76, 0xba, 0xfa, 0xbd, - 0x57, 0xbf, 0xf7, 0x51, 0xaf, 0xde, 0xaf, 0x17, 0x35, 0x07, 0x3e, 0xa5, 0x6e, 0xdf, 0xa6, 0x43, - 0x4b, 0x0f, 0x42, 0xe6, 0x93, 0x01, 0xd5, 0x1f, 0x8f, 0xa8, 0x3f, 0x6e, 0x79, 0x3e, 0x0b, 0x19, - 0xc6, 0xe9, 0xfb, 0x16, 0xbc, 0x57, 0xaf, 0x9a, 0x2c, 0x70, 0x58, 0xa0, 0xf7, 0x48, 0x00, 0xc2, - 0xfa, 0x93, 0xad, 0x1e, 0x0d, 0xc9, 0x96, 0xee, 0x91, 0x81, 0xed, 0x92, 0xd0, 0x66, 0xae, 0xd0, - 0x57, 0x5f, 0x10, 0xb2, 0x06, 0x7f, 0xd2, 0xc5, 0x03, 0xbc, 0x5a, 0x1b, 0xb0, 0x01, 0x13, 0xeb, - 0xd1, 0x2f, 0x58, 0x5d, 0x1f, 0x30, 0x36, 0x18, 0x52, 0x9d, 0x78, 0xb6, 0x4e, 0x5c, 0x97, 0x85, - 0xdc, 0x5a, 0xac, 0xa3, 0x49, 0x70, 0x3d, 0xea, 0x3b, 0x76, 0x10, 0xd8, 0xcc, 0xd5, 0x4d, 0xe6, - 0x38, 0xc9, 0x96, 0x97, 0xca, 0x65, 0xc2, 0xb1, 0x47, 0x63, 0x33, 0x17, 0x4a, 0xbc, 0xf6, 0x88, - 0x4f, 0x9c, 0x58, 0xa0, 0x2c, 0x2c, 0xb2, 0x81, 0x97, 0xa4, 0xf7, 0x4f, 0x6c, 0x3f, 0x1c, 0x91, - 0xe1, 0xc0, 0x67, 0x23, 0x4f, 0x16, 0xd2, 0xd6, 0x10, 0xfe, 0x5e, 0x14, 0x9d, 0xfb, 0xdc, 0x72, - 0x97, 0x3e, 0x1e, 0xd1, 0x20, 0xd4, 0xee, 0xa1, 0xaf, 0x64, 0x56, 0x03, 0x8f, 0xb9, 0x01, 0xc5, - 0xdf, 0x42, 0x4b, 0x02, 0xc1, 0x39, 0xe5, 0xa2, 0xb2, 0xd1, 0xb8, 0xa1, 0xb6, 0x8a, 0x91, 0x6f, - 0x09, 0x9d, 0xf6, 0xe9, 0x0f, 0x3f, 0xbd, 0x70, 0xaa, 0x0b, 0xf2, 0xda, 0x9b, 0xe8, 0xbc, 0x64, - 0xb0, 0x3d, 0xde, 0xb7, 0x1d, 0x1a, 0x84, 0xc4, 0xf1, 0x60, 0x47, 0xbc, 0x8e, 0x56, 0xc2, 0x78, - 0x8d, 0x5b, 0x5f, 0xec, 0xa6, 0x0b, 0xda, 0x01, 0x6a, 0x56, 0xa9, 0x1f, 0x1b, 0xda, 0x36, 0xfa, - 0x2a, 0xb7, 0xfd, 0x5d, 0x4a, 0xac, 0xf6, 0xc8, 0x3c, 0xa4, 0x61, 0x8c, 0xe9, 0x02, 0x6a, 0xf4, - 0xf8, 0x82, 0xe1, 0x12, 0x87, 0x72, 0xc3, 0x2b, 0x5d, 0x24, 0x96, 0xee, 0x12, 0x87, 0x6a, 0xdb, - 0x48, 0xcd, 0xa9, 0xb6, 0xc7, 0x1d, 0x2b, 0x56, 0x7f, 0x11, 0xad, 0x80, 0xba, 0x6d, 0x81, 0xf2, - 0xb2, 0x58, 0xe8, 0x58, 0xda, 0x01, 0xfa, 0x5a, 0x61, 0x57, 0x70, 0xe5, 0xdb, 0xc9, 0xb6, 0xb6, - 0xdb, 0x67, 0xe0, 0x4f, 0xb3, 0xcc, 0x1f, 0xa1, 0xd8, 0x71, 0xfb, 0x2c, 0x86, 0x15, 0xfd, 0xd6, - 0x0e, 0x24, 0x8f, 0xee, 0xf5, 0x7e, 0x44, 0xcd, 0xb9, 0x3d, 0x8a, 0x04, 0x18, 0xd7, 0x10, 0x02, - 0x0b, 0x42, 0x40, 0x2c, 0x15, 0x5c, 0x16, 0xb6, 0x73, 0x2e, 0x83, 0x7a, 0xea, 0xb2, 0x58, 0xe8, - 0x58, 0xda, 0xdf, 0x15, 0xc9, 0xe7, 0x18, 0x57, 0xea, 0x73, 0xac, 0x58, 0xe3, 0xb3, 0x50, 0x14, - 0x3e, 0xb3, 0xe4, 0x37, 0xfe, 0x21, 0x5a, 0x1b, 0x0c, 0x59, 0x8f, 0x0c, 0x0d, 0x28, 0x75, 0x83, - 0xd7, 0x3a, 0xf7, 0xa0, 0x71, 0xe3, 0x15, 0xd9, 0x92, 0x7c, 0x16, 0x5a, 0x7b, 0x5c, 0xe9, 0xa1, - 0x58, 0xda, 0x8b, 0x96, 0xba, 0x78, 0x50, 0x58, 0xd3, 0x08, 0x40, 0xbf, 0x6d, 0x07, 0xa1, 0x88, - 0x7a, 0x7c, 0x56, 0xf0, 0x2e, 0x42, 0x69, 0x47, 0x01, 0xe4, 0x97, 0x5b, 0xd0, 0x45, 0xa2, 0xf6, - 0xd3, 0x12, 0xbd, 0x0a, 0xda, 0x4f, 0xeb, 0x3e, 0x19, 0x50, 0xd0, 0xed, 0x4a, 0x9a, 0xda, 0x9f, - 0x14, 0x74, 0xae, 0xb8, 0x07, 0xc4, 0x67, 0x07, 0xad, 0x4a, 0x35, 0x11, 0x15, 0xf9, 0xe2, 0x1c, - 0x45, 0xd1, 0x48, 0x8b, 0x22, 0xc0, 0x7b, 0x19, 0x9c, 0x22, 0x2e, 0x57, 0x6a, 0x71, 0x8a, 0xfd, - 0x33, 0x40, 0xdf, 0x55, 0xa4, 0x60, 0x88, 0x74, 0x9c, 0x74, 0x30, 0xf2, 0x85, 0xba, 0x50, 0x38, - 0x7a, 0x3f, 0x57, 0xd0, 0xa5, 0x3c, 0x88, 0xf6, 0x18, 0x7c, 0xb7, 0x4e, 0x1a, 0x4e, 0xe6, 0x28, - 0x2f, 0xe4, 0x8e, 0x72, 0x26, 0x71, 0x49, 0x3c, 0xd2, 0xc4, 0x49, 0x85, 0x3d, 0x33, 0x71, 0x52, - 0x65, 0x37, 0xd2, 0xca, 0x3e, 0xc1, 0xc4, 0x5d, 0x43, 0x67, 0x39, 0xce, 0xbb, 0xbb, 0xfb, 0x71, - 0x80, 0x5e, 0x40, 0xcb, 0x21, 0x3b, 0xa4, 0x6e, 0x7a, 0x5e, 0xbf, 0xc8, 0x9f, 0x3b, 0x96, 0xf6, - 0x03, 0xe8, 0x22, 0x22, 0xa6, 0x5c, 0x27, 0x39, 0xac, 0x2b, 0x0e, 0x0d, 0x89, 0x61, 0x91, 0x90, - 0x40, 0x50, 0xb5, 0xea, 0x4a, 0xbc, 0x43, 0x43, 0xf2, 0x36, 0x09, 0x49, 0x77, 0xd9, 0x81, 0x5f, - 0x89, 0x69, 0xe1, 0xf1, 0xe7, 0x31, 0x2d, 0x34, 0x4b, 0x4c, 0x7f, 0x1f, 0x3d, 0xcf, 0x4d, 0xf3, - 0x63, 0x2b, 0x5b, 0x7e, 0xab, 0x68, 0xf9, 0x52, 0x99, 0x65, 0xae, 0x58, 0x62, 0xf8, 0xa7, 0x0a, - 0x5a, 0x17, 0x77, 0x10, 0x1b, 0xda, 0xe6, 0x78, 0x97, 0xf9, 0x3b, 0xa6, 0xc9, 0x46, 0x6e, 0xd2, - 0x5b, 0x55, 0xb4, 0xec, 0xd3, 0x80, 0x8d, 0x7c, 0x33, 0x6e, 0xac, 0xc9, 0x33, 0xbe, 0x85, 0xbe, - 0xec, 0xf9, 0xb6, 0x6b, 0xda, 0x1e, 0x19, 0x1a, 0xc4, 0xb2, 0x7c, 0x1a, 0x04, 0xa2, 0x8e, 0xda, - 0xe7, 0x3e, 0xfe, 0x60, 0x73, 0x0d, 0x92, 0xb9, 0x23, 0xde, 0x3c, 0x08, 0x7d, 0xdb, 0x1d, 0x74, - 0x9f, 0x4b, 0x54, 0x60, 0x5d, 0x7b, 0x18, 0xdf, 0xa2, 0x05, 0x08, 0xe0, 0xe4, 0x4d, 0xb4, 0xe4, - 0xf1, 0x77, 0xe0, 0xe1, 0x79, 0xd9, 0xc3, 0x74, 0xce, 0x68, 0x09, 0x03, 0x5d, 0x10, 0xd6, 0x3e, - 0x89, 0x7d, 0x7b, 0x48, 0x7d, 0xbb, 0x3f, 0xbe, 0x9f, 0x08, 0xc6, 0xbe, 0xbd, 0x86, 0x96, 0x99, - 0x47, 0x7d, 0x12, 0x32, 0x5f, 0xf8, 0x36, 0x03, 0x76, 0x22, 0x59, 0x7b, 0x88, 0xf3, 0xb7, 0xcd, - 0x62, 0xfe, 0xb6, 0xc1, 0x6d, 0xd4, 0x20, 0x66, 0x54, 0xbb, 0x46, 0x34, 0xb3, 0x9c, 0x3b, 0x7d, - 0x51, 0xd9, 0x38, 0x93, 0x4d, 0x9b, 0xe4, 0xd4, 0x0e, 0x97, 0xdc, 0x1f, 0x7b, 0xb4, 0x8b, 0x48, - 0xf2, 0x3b, 0x09, 0x5a, 0xd1, 0xb7, 0x34, 0x68, 0xb4, 0xdf, 0xa7, 0x66, 0xc8, 0x5d, 0x3b, 0x53, - 0x19, 0xb4, 0x5b, 0x5c, 0xa8, 0x0b, 0xc2, 0xda, 0x63, 0xa8, 0xb4, 0xe8, 0x36, 0x13, 0x17, 0x07, - 0x04, 0x6b, 0x1b, 0x35, 0xf8, 0xdd, 0x62, 0xb0, 0x1f, 0xbb, 0xb4, 0x3e, 0x5e, 0x88, 0x0b, 0xdf, - 0x8b, 0x64, 0xf1, 0x79, 0x24, 0x9e, 0xe4, 0x80, 0xad, 0xf0, 0x15, 0xde, 0xf4, 0x1e, 0x4a, 0x17, - 0x3b, 0x6c, 0x09, 0x3e, 0xbc, 0x11, 0x2b, 0x4a, 0xd7, 0xe7, 0xf9, 0xca, 0xf2, 0xe6, 0x3d, 0x46, - 0xd8, 0xe5, 0x03, 0xc3, 0x6f, 0x14, 0xf0, 0x25, 0xea, 0x60, 0x19, 0x5f, 0x4e, 0xaa, 0x81, 0xe6, - 0x62, 0xb2, 0x30, 0x7f, 0x4c, 0xb4, 0xdf, 0x2b, 0xe0, 0xb5, 0x04, 0x0e, 0xbc, 0xde, 0x2b, 0x41, - 0xf7, 0x79, 0x3a, 0x23, 0x7e, 0x2b, 0x86, 0x27, 0x9a, 0xf4, 0x02, 0x6f, 0xd2, 0x35, 0xf1, 0x43, - 0x49, 0xfc, 0x02, 0xed, 0x2f, 0x0a, 0x7a, 0x31, 0x9b, 0x99, 0x3b, 0xd4, 0xe9, 0x51, 0x3f, 0x0e, - 0xe3, 0x75, 0xb4, 0xe4, 0xf0, 0x85, 0xda, 0x6a, 0x00, 0xb9, 0x63, 0x04, 0x2c, 0x57, 0x44, 0x8b, - 0xf9, 0x22, 0xa2, 0x70, 0xd6, 0x0b, 0x50, 0x21, 0xa8, 0xb7, 0xd0, 0xaa, 0x50, 0x97, 0x10, 0xe7, - 0xba, 0xb0, 0x74, 0x28, 0x64, 0x0b, 0x02, 0xb1, 0x78, 0xd0, 0xfa, 0x30, 0x28, 0x26, 0xbd, 0x2a, - 0x53, 0x57, 0xb3, 0x9a, 0xe5, 0x35, 0x84, 0xd3, 0x66, 0x09, 0x69, 0x89, 0x6f, 0xdd, 0xb4, 0x27, - 0x8a, 0x44, 0x58, 0xda, 0x3e, 0x44, 0x3e, 0xbf, 0xcf, 0xf1, 0x3a, 0xe2, 0x4d, 0xa8, 0x39, 0xb1, - 0x9c, 0x1b, 0x71, 0x85, 0x8c, 0x34, 0xe2, 0x8a, 0x85, 0x8e, 0xa5, 0xdd, 0x87, 0xc9, 0x48, 0x56, - 0x3b, 0x1e, 0x90, 0xf7, 0x15, 0xa0, 0x62, 0xb7, 0x99, 0x79, 0xb8, 0x4b, 0x69, 0x7a, 0x30, 0xa3, - 0x20, 0x39, 0xc4, 0x1f, 0x1b, 0x81, 0x97, 0x5c, 0x29, 0xca, 0x1c, 0x57, 0x4a, 0xa4, 0xf3, 0xc0, - 0x83, 0xf5, 0xc8, 0x1d, 0xd3, 0xa7, 0x24, 0xa4, 0x06, 0x09, 0x79, 0x8c, 0x17, 0xbb, 0xcb, 0x62, - 0x61, 0x27, 0xc4, 0x97, 0xd0, 0xaa, 0x47, 0xc6, 0x43, 0x46, 0x2c, 0x23, 0xb0, 0xdf, 0x11, 0xb5, - 0x74, 0xba, 0xdb, 0x80, 0xb5, 0x07, 0xf6, 0x3b, 0x54, 0x1b, 0xa2, 0xb5, 0x2c, 0x3c, 0x70, 0x77, - 0x1f, 0x2d, 0x11, 0x27, 0xba, 0x9b, 0x00, 0xd3, 0x1b, 0x11, 0xe7, 0xfa, 0xe4, 0xd3, 0x0b, 0x97, - 0x07, 0x76, 0xf8, 0x68, 0xd4, 0x6b, 0x99, 0xcc, 0x01, 0xa6, 0x0d, 0x7f, 0x36, 0x03, 0xeb, 0x10, - 0x98, 0x69, 0xc7, 0x0d, 0x3f, 0xfe, 0x60, 0x13, 0x81, 0x07, 0x1d, 0x37, 0xec, 0x82, 0xad, 0x1b, - 0xef, 0xab, 0xe8, 0x0b, 0x7c, 0x3b, 0x3c, 0x45, 0x4b, 0x82, 0xcd, 0xe1, 0xcb, 0x65, 0xc7, 0xb4, - 0xc8, 0x69, 0xd5, 0x2b, 0xb5, 0x72, 0x02, 0xba, 0xa6, 0xbd, 0xfb, 0x9f, 0xff, 0xff, 0x6a, 0x61, - 0x1d, 0xab, 0x7a, 0x25, 0x03, 0xc7, 0x7f, 0x8b, 0x9b, 0x52, 0x81, 0x91, 0xe2, 0xad, 0x9a, 0x7d, - 0x8a, 0xe4, 0x57, 0xbd, 0x71, 0x14, 0x15, 0x40, 0xd9, 0xe2, 0x28, 0x37, 0xf0, 0xe5, 0x6a, 0x94, - 0xfa, 0x24, 0x61, 0xd0, 0x53, 0xfc, 0x5b, 0x05, 0xa1, 0x94, 0x6c, 0xe2, 0xab, 0x95, 0x5b, 0x16, - 0x78, 0xb0, 0xfa, 0xca, 0x5c, 0xb2, 0x80, 0xeb, 0x26, 0xc7, 0xa5, 0xe3, 0xcd, 0x32, 0x5c, 0x8f, - 0x28, 0xb1, 0x0c, 0x31, 0x00, 0xe8, 0x13, 0x69, 0x36, 0x98, 0xe2, 0x3f, 0x2b, 0xe8, 0x4c, 0x96, - 0x46, 0xe3, 0xd6, 0x1c, 0xdb, 0x4a, 0x27, 0xf3, 0x68, 0x30, 0xb7, 0x39, 0xcc, 0x57, 0xf1, 0x56, - 0x0d, 0x4c, 0xa3, 0x17, 0x1d, 0xf4, 0x04, 0xac, 0x6d, 0x4d, 0xf1, 0x7b, 0x0a, 0xfa, 0x52, 0x6a, - 0xf1, 0xee, 0xee, 0x3e, 0x7e, 0xa9, 0x72, 0xe7, 0x74, 0xd4, 0x56, 0xab, 0x23, 0x5e, 0x98, 0xb0, - 0xb5, 0x6f, 0x72, 0x74, 0xd7, 0x71, 0xab, 0x0e, 0x9d, 0xdb, 0x0f, 0xf5, 0x49, 0x3c, 0xc1, 0x4f, - 0xf1, 0x5f, 0x21, 0xc9, 0x62, 0x3c, 0xae, 0x49, 0x72, 0xe6, 0xd3, 0x40, 0x4d, 0xf4, 0xb2, 0x74, - 0x5d, 0xfb, 0x0e, 0xc7, 0xf7, 0x26, 0x7e, 0xbd, 0x12, 0x9f, 0x18, 0xe2, 0xb2, 0x49, 0xd6, 0x27, - 0xd2, 0xb4, 0x97, 0xa6, 0x3c, 0xfd, 0x8c, 0x50, 0x93, 0xf2, 0xc2, 0xf7, 0x86, 0xa3, 0x81, 0xae, - 0x4f, 0x39, 0xc0, 0x83, 0x94, 0x27, 0x5f, 0x32, 0xd2, 0x94, 0x27, 0x84, 0xe5, 0xb8, 0x29, 0x2f, - 0x30, 0x9f, 0x39, 0x52, 0x1e, 0x07, 0x2f, 0x9b, 0xf2, 0x5f, 0x2a, 0xa8, 0x21, 0x7d, 0x31, 0xc0, - 0xd5, 0x21, 0x29, 0x7e, 0xbb, 0x50, 0xaf, 0xcd, 0x27, 0x0c, 0x10, 0x37, 0x38, 0x44, 0x0d, 0x5f, - 0x2c, 0x83, 0x38, 0xb4, 0x83, 0x10, 0xaa, 0x32, 0xc0, 0xbf, 0x03, 0x50, 0xc0, 0x86, 0x6b, 0x40, - 0x65, 0xbf, 0x21, 0xd4, 0x80, 0xca, 0x11, 0xec, 0xd9, 0x71, 0xe3, 0xa0, 0x44, 0xdc, 0x82, 0x5c, - 0xc3, 0xf9, 0x87, 0x82, 0x9e, 0x2f, 0xfd, 0x76, 0x80, 0x6f, 0xce, 0xb3, 0x7f, 0xe1, 0x5b, 0xc3, - 0x11, 0x61, 0xef, 0x70, 0xd8, 0xaf, 0xe3, 0xed, 0x3a, 0xd8, 0x51, 0x35, 0x26, 0xcd, 0x27, 0xd3, - 0x87, 0x7e, 0xad, 0xa0, 0xd5, 0x64, 0x88, 0x9b, 0xbb, 0x26, 0x5f, 0xae, 0x14, 0xca, 0x53, 0xe6, - 0x39, 0x5a, 0x39, 0xcc, 0x99, 0xd9, 0x8a, 0xfc, 0x57, 0xcc, 0x26, 0xf2, 0x34, 0x15, 0x5f, 0xaf, - 0xbe, 0xe7, 0xca, 0x49, 0xb5, 0xba, 0x75, 0x04, 0x0d, 0x40, 0x7d, 0x87, 0xa3, 0xde, 0xc3, 0xb7, - 0x4a, 0x2f, 0x46, 0x31, 0xba, 0xf5, 0x99, 0x6f, 0x10, 0xa1, 0xa7, 0x4f, 0xe2, 0xc1, 0x73, 0xaa, - 0x4f, 0x0a, 0x24, 0x7d, 0x8a, 0xff, 0xad, 0xa0, 0xe7, 0xf2, 0xd4, 0x71, 0x86, 0x23, 0x15, 0x0c, - 0x7a, 0x86, 0x23, 0x55, 0xbc, 0x54, 0xdb, 0xe7, 0x8e, 0xdc, 0xc5, 0xb7, 0xcb, 0x1c, 0x79, 0xc2, - 0xb5, 0x0c, 0xe9, 0x7f, 0x07, 0x93, 0x98, 0x77, 0x4f, 0xf3, 0x5d, 0x57, 0xa2, 0xd0, 0x53, 0xfc, - 0x47, 0x05, 0xad, 0x24, 0x55, 0x83, 0x5f, 0x9e, 0xd9, 0x40, 0xe5, 0x91, 0x5d, 0xbd, 0x3a, 0x8f, - 0xe8, 0x3c, 0xd5, 0x9d, 0x56, 0x8e, 0x3e, 0x91, 0x38, 0xce, 0x34, 0x7e, 0x12, 0xe7, 0xf3, 0x3d, - 0x05, 0xad, 0x24, 0x8c, 0x6f, 0x06, 0xce, 0x3c, 0x65, 0x9d, 0x81, 0xb3, 0x40, 0x20, 0xb5, 0xd7, - 0x38, 0xce, 0x16, 0xbe, 0x56, 0x79, 0x0a, 0x4b, 0x70, 0xe2, 0x3f, 0x28, 0xe8, 0x6c, 0x8e, 0x3d, - 0x61, 0xbd, 0x3e, 0x3a, 0x19, 0x4a, 0xa8, 0x5e, 0x9f, 0x5f, 0x01, 0xc0, 0x6e, 0x72, 0xb0, 0x57, - 0xf0, 0x37, 0x6a, 0x8e, 0x23, 0x30, 0xc8, 0x7f, 0xc6, 0xcc, 0x21, 0xcb, 0x8c, 0x66, 0xdc, 0xb1, - 0xa5, 0x54, 0x4d, 0xd5, 0xe7, 0x96, 0x07, 0x9c, 0xb7, 0x39, 0xce, 0x5d, 0xfc, 0x76, 0xcd, 0x01, - 0x84, 0xd0, 0x96, 0x1e, 0xbf, 0x98, 0xf6, 0x4d, 0xa3, 0xab, 0xe4, 0x6c, 0x8e, 0x53, 0xcd, 0x98, - 0x6b, 0x0a, 0x7c, 0x6d, 0xc6, 0x88, 0x50, 0x24, 0x69, 0xb3, 0xeb, 0x01, 0xa0, 0xc3, 0x74, 0x90, - 0x90, 0xc0, 0x29, 0xfe, 0x99, 0x82, 0x56, 0x65, 0x12, 0x84, 0xab, 0xa9, 0x46, 0x96, 0xc5, 0xa9, - 0x1b, 0xf5, 0x82, 0x80, 0xec, 0xeb, 0x1c, 0x59, 0x13, 0xaf, 0x97, 0x56, 0x2a, 0x33, 0x0f, 0x8d, - 0x3e, 0xa5, 0xed, 0xce, 0x87, 0x4f, 0x9b, 0xca, 0x47, 0x4f, 0x9b, 0xca, 0xff, 0x9e, 0x36, 0x95, - 0x5f, 0x3c, 0x6b, 0x9e, 0xfa, 0xe8, 0x59, 0xf3, 0xd4, 0x7f, 0x9f, 0x35, 0x4f, 0x1d, 0xe8, 0x12, - 0xef, 0xea, 0xb9, 0xbd, 0x4d, 0xf3, 0x11, 0xb1, 0x5d, 0xd9, 0xd6, 0x4f, 0xb2, 0xff, 0x43, 0xec, - 0x2d, 0xf1, 0xff, 0x0f, 0xbe, 0xfa, 0x59, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x18, 0x28, 0xf4, - 0x7d, 0x1d, 0x00, 0x00, + // 2243 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x5a, 0xcb, 0x6f, 0x1c, 0x49, + 0x19, 0x4f, 0xdb, 0x89, 0x63, 0x97, 0x4d, 0x12, 0x0a, 0xef, 0xae, 0x33, 0x89, 0x27, 0x49, 0x2f, + 0x24, 0xde, 0x6c, 0x3c, 0x1d, 0x3b, 0x31, 0xc2, 0x64, 0x13, 0x64, 0x6f, 0x6c, 0x33, 0x52, 0x1e, + 0x66, 0x62, 0x05, 0x11, 0x09, 0xb5, 0x6a, 0xba, 0x6b, 0x26, 0xbd, 0x9e, 0xe9, 0xea, 0x74, 0xf7, + 0xc4, 0x3b, 0x3b, 0x1a, 0x21, 0xf6, 0x00, 0x1c, 0x11, 0x08, 0x69, 0x85, 0x40, 0x02, 0x21, 0x10, + 0x70, 0x41, 0xa0, 0xbd, 0x70, 0xe2, 0xc2, 0x61, 0x25, 0x84, 0xb4, 0x5a, 0x2e, 0x68, 0x0f, 0x2b, + 0x94, 0xf0, 0x1f, 0xf0, 0x0f, 0xa0, 0xae, 0xfa, 0xba, 0xbb, 0xfa, 0x31, 0xd3, 0xe3, 0xf5, 0x9c, + 0x32, 0x53, 0xf3, 0x3d, 0x7e, 0xdf, 0xa3, 0xbe, 0xaa, 0xfa, 0xc5, 0xa8, 0xdc, 0x74, 0x29, 0xb5, + 0x1b, 0x16, 0x6d, 0x99, 0x9a, 0xe7, 0x33, 0x97, 0x34, 0xa9, 0xf6, 0xac, 0x43, 0xdd, 0x6e, 0xc5, + 0x71, 0x99, 0xcf, 0x30, 0x8e, 0x7f, 0xaf, 0xc0, 0xef, 0xa5, 0xab, 0x06, 0xf3, 0xda, 0xcc, 0xd3, + 0xea, 0xc4, 0x03, 0x61, 0xed, 0xf9, 0x4a, 0x9d, 0xfa, 0x64, 0x45, 0x73, 0x48, 0xd3, 0xb2, 0x89, + 0x6f, 0x31, 0x5b, 0xe8, 0x97, 0xce, 0x0a, 0x59, 0x9d, 0x7f, 0xd3, 0xc4, 0x17, 0xf8, 0x69, 0xbe, + 0xc9, 0x9a, 0x4c, 0xac, 0x07, 0x9f, 0x60, 0xf5, 0x7c, 0x93, 0xb1, 0x66, 0x8b, 0x6a, 0xc4, 0xb1, + 0x34, 0x62, 0xdb, 0xcc, 0xe7, 0xd6, 0x42, 0x1d, 0x55, 0x82, 0xeb, 0x50, 0xb7, 0x6d, 0x79, 0x9e, + 0xc5, 0x6c, 0xcd, 0x60, 0xed, 0x76, 0xe4, 0xf2, 0x52, 0xbe, 0x8c, 0xdf, 0x75, 0x68, 0x68, 0xe6, + 0x42, 0x4e, 0xd4, 0x0e, 0x71, 0x49, 0x3b, 0x14, 0xc8, 0x4b, 0x8b, 0x6c, 0xe0, 0x75, 0xe9, 0xf7, + 0xe7, 0x96, 0xeb, 0x77, 0x48, 0xab, 0xe9, 0xb2, 0x8e, 0x23, 0x0b, 0xa9, 0xf3, 0x08, 0x7f, 0x2b, + 0xc8, 0xce, 0x2e, 0xb7, 0x5c, 0xa3, 0xcf, 0x3a, 0xd4, 0xf3, 0xd5, 0x87, 0xe8, 0x4b, 0x89, 0x55, + 0xcf, 0x61, 0xb6, 0x47, 0xf1, 0xd7, 0xd0, 0x94, 0x40, 0xb0, 0xa0, 0x5c, 0x54, 0x96, 0x66, 0x57, + 0x4b, 0x95, 0x6c, 0xe6, 0x2b, 0x42, 0x67, 0xf3, 0xf8, 0x47, 0x9f, 0x5d, 0x38, 0x56, 0x03, 0x79, + 0xf5, 0x36, 0x5a, 0x94, 0x0c, 0x6e, 0x76, 0xf7, 0xac, 0x36, 0xf5, 0x7c, 0xd2, 0x76, 0xc0, 0x23, + 0x3e, 0x8f, 0x66, 0xfc, 0x70, 0x8d, 0x5b, 0x9f, 0xac, 0xc5, 0x0b, 0xea, 0x13, 0x54, 0x1e, 0xa4, + 0x7e, 0x64, 0x68, 0xeb, 0xe8, 0x55, 0x6e, 0xfb, 0x9b, 0x94, 0x98, 0x9b, 0x1d, 0x63, 0x9f, 0xfa, + 0x21, 0xa6, 0x0b, 0x68, 0xb6, 0xce, 0x17, 0x74, 0x9b, 0xb4, 0x29, 0x37, 0x3c, 0x53, 0x43, 0x62, + 0xe9, 0x01, 0x69, 0x53, 0x75, 0x1d, 0x95, 0x52, 0xaa, 0x9b, 0xdd, 0xaa, 0x19, 0xaa, 0x9f, 0x43, + 0x33, 0xa0, 0x6e, 0x99, 0xa0, 0x3c, 0x2d, 0x16, 0xaa, 0xa6, 0xfa, 0x04, 0xbd, 0x96, 0xf1, 0x0a, + 0xa1, 0x7c, 0x23, 0x72, 0x6b, 0xd9, 0x0d, 0x06, 0xf1, 0x94, 0xf3, 0xe2, 0x11, 0x8a, 0x55, 0xbb, + 0xc1, 0x42, 0x58, 0xc1, 0x67, 0xf5, 0x89, 0x14, 0xd1, 0xc3, 0xfa, 0x3b, 0xd4, 0x18, 0x39, 0xa2, + 0x40, 0x80, 0x71, 0x0d, 0x21, 0x30, 0x21, 0x04, 0xc4, 0x52, 0x26, 0x64, 0x61, 0x3b, 0x15, 0x32, + 0xa8, 0xc7, 0x21, 0x8b, 0x85, 0xaa, 0xa9, 0xfe, 0x55, 0x91, 0x62, 0x0e, 0x71, 0xc5, 0x31, 0x87, + 0x8a, 0x05, 0x31, 0x0b, 0x45, 0x11, 0x33, 0x8b, 0x3e, 0xe3, 0xef, 0xa2, 0xf9, 0x66, 0x8b, 0xd5, + 0x49, 0x4b, 0x87, 0x56, 0xd7, 0x79, 0xaf, 0xf3, 0x08, 0x66, 0x57, 0xdf, 0x94, 0x2d, 0xc9, 0x7b, + 0xa1, 0xb2, 0xc3, 0x95, 0x1e, 0x8b, 0xa5, 0x9d, 0x60, 0xa9, 0x86, 0x9b, 0x99, 0x35, 0x95, 0x00, + 0xf4, 0x7b, 0x96, 0xe7, 0x8b, 0xac, 0x87, 0x7b, 0x05, 0x6f, 0x23, 0x14, 0x4f, 0x14, 0x40, 0x7e, + 0xb9, 0x02, 0x53, 0x24, 0x18, 0x3f, 0x15, 0x31, 0xab, 0x60, 0xfc, 0x54, 0x76, 0x49, 0x93, 0x82, + 0x6e, 0x4d, 0xd2, 0x54, 0x7f, 0xa7, 0xa0, 0x85, 0xac, 0x0f, 0xc8, 0xcf, 0x06, 0x9a, 0x93, 0x7a, + 0x22, 0x68, 0xf2, 0xc9, 0x11, 0x9a, 0x62, 0x36, 0x6e, 0x0a, 0x0f, 0xef, 0x24, 0x70, 0x8a, 0xbc, + 0x5c, 0x29, 0xc4, 0x29, 0xfc, 0x27, 0x80, 0xbe, 0xaf, 0x48, 0xc9, 0x10, 0xe5, 0x18, 0x77, 0x32, + 0xd2, 0x8d, 0x3a, 0x91, 0xd9, 0x7a, 0x3f, 0x52, 0xd0, 0xa5, 0x34, 0x88, 0xcd, 0x2e, 0xc4, 0x6e, + 0x8e, 0x1b, 0x4e, 0x62, 0x2b, 0x4f, 0xa4, 0xb6, 0x72, 0xa2, 0x70, 0x51, 0x3e, 0xe2, 0xc2, 0x49, + 0x8d, 0x3d, 0xb4, 0x70, 0x52, 0x67, 0xcf, 0xc6, 0x9d, 0x3d, 0xc6, 0xc2, 0x5d, 0x43, 0xa7, 0x39, + 0xce, 0x07, 0xdb, 0x7b, 0x61, 0x82, 0xce, 0xa2, 0x69, 0x9f, 0xed, 0x53, 0x3b, 0xde, 0xaf, 0x27, + 0xf9, 0xf7, 0xaa, 0xa9, 0x7e, 0x07, 0xa6, 0x88, 0xc8, 0x29, 0xd7, 0x89, 0x36, 0xeb, 0x4c, 0x9b, + 0xfa, 0x44, 0x37, 0x89, 0x4f, 0x20, 0xa9, 0xea, 0xe0, 0x4e, 0xbc, 0x4f, 0x7d, 0x72, 0x97, 0xf8, + 0xa4, 0x36, 0xdd, 0x86, 0x4f, 0x91, 0x69, 0x11, 0xf1, 0xe7, 0x31, 0x2d, 0x34, 0x73, 0x4c, 0x7f, + 0x1b, 0xbd, 0xc2, 0x4d, 0xf3, 0x6d, 0x2b, 0x5b, 0xbe, 0x93, 0xb5, 0x7c, 0x29, 0xcf, 0x32, 0x57, + 0xcc, 0x31, 0xfc, 0x7d, 0x05, 0x9d, 0x17, 0x67, 0x10, 0x6b, 0x59, 0x46, 0x77, 0x9b, 0xb9, 0x1b, + 0x86, 0xc1, 0x3a, 0x76, 0x34, 0x5b, 0x4b, 0x68, 0xda, 0xa5, 0x1e, 0xeb, 0xb8, 0x46, 0x38, 0x58, + 0xa3, 0xef, 0x78, 0x0b, 0x7d, 0xd1, 0x71, 0x2d, 0xdb, 0xb0, 0x1c, 0xd2, 0xd2, 0x89, 0x69, 0xba, + 0xd4, 0xf3, 0x44, 0x1f, 0x6d, 0x2e, 0x7c, 0xf2, 0xe1, 0xf2, 0x3c, 0x14, 0x73, 0x43, 0xfc, 0xf2, + 0xc8, 0x77, 0x2d, 0xbb, 0x59, 0x3b, 0x13, 0xa9, 0xc0, 0xba, 0xfa, 0x38, 0x3c, 0x45, 0x33, 0x10, + 0x20, 0xc8, 0x35, 0x34, 0xe5, 0xf0, 0xdf, 0x20, 0xc2, 0x45, 0x39, 0xc2, 0xf8, 0x9e, 0x51, 0x11, + 0x06, 0x6a, 0x20, 0xac, 0x7e, 0x1a, 0xc6, 0xf6, 0x98, 0xba, 0x56, 0xa3, 0xbb, 0x1b, 0x09, 0x86, + 0xb1, 0xdd, 0x44, 0xd3, 0xcc, 0xa1, 0x2e, 0xf1, 0x99, 0x2b, 0x62, 0x1b, 0x02, 0x3b, 0x92, 0x2c, + 0xdc, 0xc4, 0xe9, 0xd3, 0x66, 0x32, 0x7d, 0xda, 0xe0, 0x4d, 0x34, 0x4b, 0x8c, 0xa0, 0x77, 0xf5, + 0xe0, 0xce, 0xb2, 0x70, 0xfc, 0xa2, 0xb2, 0x74, 0x2a, 0x59, 0x36, 0x29, 0xa8, 0x0d, 0x2e, 0xb9, + 0xd7, 0x75, 0x68, 0x0d, 0x91, 0xe8, 0x73, 0x94, 0xb4, 0x6c, 0x6c, 0x71, 0xd2, 0x68, 0xa3, 0x41, + 0x0d, 0x9f, 0x87, 0x76, 0x6a, 0x60, 0xd2, 0xb6, 0xb8, 0x50, 0x0d, 0x84, 0xd5, 0x67, 0xd0, 0x69, + 0xc1, 0x69, 0x26, 0x0e, 0x0e, 0x48, 0xd6, 0x3a, 0x9a, 0xe5, 0x67, 0x8b, 0xce, 0x0e, 0x6c, 0x5a, + 0x9c, 0x2f, 0xc4, 0x85, 0x1f, 0x06, 0xb2, 0x78, 0x11, 0x89, 0x6f, 0x72, 0xc2, 0x66, 0xf8, 0x0a, + 0x1f, 0x7a, 0x8f, 0xa5, 0x83, 0x1d, 0x5c, 0x42, 0x0c, 0x6f, 0x85, 0x8a, 0xd2, 0xf1, 0xb9, 0x38, + 0xb0, 0xbd, 0xf9, 0x8c, 0x11, 0x76, 0xf9, 0x85, 0xe1, 0xe7, 0x0a, 0xc4, 0x12, 0x4c, 0xb0, 0x44, + 0x2c, 0xe3, 0x1a, 0xa0, 0xa9, 0x9c, 0x4c, 0x8c, 0x9e, 0x13, 0xf5, 0xd7, 0x0a, 0x44, 0x2d, 0x81, + 0x83, 0xa8, 0x77, 0x72, 0xd0, 0x7d, 0x9e, 0xc9, 0x88, 0xef, 0x84, 0xf0, 0xc4, 0x90, 0x9e, 0xe0, + 0x43, 0xba, 0x20, 0x7f, 0x28, 0xca, 0x9f, 0xa7, 0xfe, 0x41, 0x41, 0xe7, 0x92, 0x95, 0xb9, 0x4f, + 0xdb, 0x75, 0xea, 0x86, 0x69, 0xbc, 0x8e, 0xa6, 0xda, 0x7c, 0xa1, 0xb0, 0x1b, 0x40, 0xee, 0x08, + 0x09, 0x4b, 0x35, 0xd1, 0x64, 0xba, 0x89, 0x28, 0xec, 0xf5, 0x0c, 0x54, 0x48, 0xea, 0x16, 0x9a, + 0x13, 0xea, 0x12, 0xe2, 0xd4, 0x14, 0x96, 0x36, 0x85, 0x6c, 0x41, 0x20, 0x16, 0x5f, 0xd4, 0x06, + 0x5c, 0x14, 0xa3, 0x59, 0x95, 0xe8, 0xab, 0x61, 0xc3, 0xf2, 0x1a, 0xc2, 0xf1, 0xb0, 0x84, 0xb2, + 0x84, 0xa7, 0x6e, 0x3c, 0x13, 0x45, 0x21, 0x4c, 0x75, 0x0f, 0x32, 0x9f, 0xf6, 0x73, 0xb4, 0x89, + 0xb8, 0x06, 0x3d, 0x27, 0x96, 0x53, 0x57, 0x5c, 0x21, 0x23, 0x5d, 0x71, 0xc5, 0x42, 0xd5, 0x54, + 0x77, 0xe1, 0x66, 0x24, 0xab, 0x1d, 0x0d, 0xc8, 0x2f, 0x15, 0x78, 0x8a, 0xdd, 0x63, 0xc6, 0xfe, + 0x36, 0xa5, 0xf1, 0xc6, 0x0c, 0x92, 0xd4, 0x26, 0x6e, 0x57, 0xf7, 0x9c, 0xe8, 0x48, 0x51, 0x46, + 0x38, 0x52, 0x02, 0x9d, 0x47, 0x0e, 0xac, 0x07, 0xe1, 0x18, 0x2e, 0x25, 0x3e, 0xd5, 0x89, 0xcf, + 0x73, 0x3c, 0x59, 0x9b, 0x16, 0x0b, 0x1b, 0x3e, 0xbe, 0x84, 0xe6, 0x1c, 0xd2, 0x6d, 0x31, 0x62, + 0xea, 0x9e, 0xf5, 0x9e, 0xe8, 0xa5, 0xe3, 0xb5, 0x59, 0x58, 0x7b, 0x64, 0xbd, 0x47, 0xd5, 0x16, + 0x9a, 0x4f, 0xc2, 0x83, 0x70, 0xf7, 0xd0, 0x14, 0x69, 0x07, 0x67, 0x13, 0x60, 0x7a, 0x2b, 0x78, + 0x73, 0x7d, 0xfa, 0xd9, 0x85, 0xcb, 0x4d, 0xcb, 0x7f, 0xda, 0xa9, 0x57, 0x0c, 0xd6, 0x86, 0x97, + 0x36, 0xfc, 0xb3, 0xec, 0x99, 0xfb, 0xf0, 0x32, 0xad, 0xda, 0xfe, 0x27, 0x1f, 0x2e, 0x23, 0x88, + 0xa0, 0x6a, 0xfb, 0x35, 0xb0, 0xa5, 0xde, 0x91, 0xb6, 0x99, 0xb8, 0x5d, 0x6c, 0xbd, 0xeb, 0xbb, + 0x64, 0xe4, 0x07, 0x9b, 0xdc, 0xfb, 0x09, 0xfd, 0xa8, 0xf7, 0x11, 0x0d, 0x16, 0xe4, 0x31, 0x7a, + 0x39, 0x6f, 0x0c, 0x54, 0x6d, 0x9f, 0xba, 0x36, 0x69, 0x49, 0x97, 0xed, 0x19, 0xae, 0xc9, 0xe7, + 0xe9, 0x6d, 0xe8, 0xfd, 0xaa, 0xb7, 0xeb, 0x5a, 0x06, 0x7d, 0xfb, 0x29, 0xb1, 0x9b, 0xd4, 0x1c, + 0x19, 0xe5, 0xff, 0x4e, 0x40, 0x98, 0x69, 0x7d, 0x40, 0xb9, 0x80, 0x4e, 0x1a, 0x62, 0x89, 0x2b, + 0x4f, 0xd7, 0xc2, 0xaf, 0xf8, 0x1d, 0x84, 0x8d, 0x8e, 0xeb, 0x52, 0xdb, 0xd7, 0x5d, 0x4a, 0x4c, + 0xdd, 0x09, 0xd4, 0x61, 0x78, 0x1c, 0xa6, 0x02, 0x77, 0xa9, 0x21, 0x55, 0xe0, 0x2e, 0x35, 0x6a, + 0x67, 0xc0, 0x6e, 0x8d, 0x12, 0x93, 0x83, 0xc2, 0x3d, 0x74, 0x2e, 0xf4, 0x15, 0x75, 0xa2, 0xcf, + 0x5c, 0x0a, 0x4e, 0x27, 0xc7, 0xe0, 0x74, 0x01, 0x1c, 0xec, 0x42, 0xd7, 0x06, 0xe6, 0x85, 0xf3, + 0xef, 0xa1, 0xc5, 0xd0, 0xb9, 0x47, 0x0d, 0x66, 0x9b, 0x69, 0xf7, 0xc7, 0xc7, 0xe0, 0xbe, 0x04, + 0x2e, 0x1e, 0x85, 0x1e, 0x24, 0x00, 0x75, 0x74, 0xca, 0xa6, 0x07, 0x72, 0x96, 0x4f, 0x8c, 0xc1, + 0xe3, 0x9c, 0x4d, 0x0f, 0xe2, 0x0c, 0x7b, 0xe8, 0xb5, 0xc0, 0x47, 0x5e, 0x76, 0xa7, 0xc6, 0xe0, + 0x6c, 0xde, 0xa6, 0x07, 0xd9, 0xcc, 0x1e, 0xa0, 0xb3, 0x81, 0xd3, 0xfc, 0xac, 0x9e, 0x1c, 0x83, + 0xdb, 0x57, 0x6d, 0x7a, 0x90, 0x93, 0xd1, 0xd5, 0x1f, 0x2c, 0xa2, 0x13, 0xbc, 0xeb, 0x71, 0x1f, + 0x4d, 0x09, 0xa6, 0x06, 0xe7, 0xee, 0xbd, 0x2c, 0x5f, 0x55, 0xba, 0x52, 0x28, 0x27, 0xb6, 0x8e, + 0xaa, 0xbe, 0xff, 0xaf, 0xff, 0xfe, 0x74, 0xe2, 0x3c, 0x2e, 0x69, 0x03, 0xd9, 0x35, 0xfc, 0xa7, + 0xf0, 0xc2, 0x91, 0x61, 0x9b, 0xf0, 0x4a, 0x81, 0x9f, 0x2c, 0xb1, 0x55, 0x5a, 0x3d, 0x8c, 0x0a, + 0xa0, 0xac, 0x70, 0x94, 0x4b, 0xf8, 0xf2, 0x60, 0x94, 0x5a, 0x2f, 0x62, 0xc7, 0xfa, 0xf8, 0x17, + 0x0a, 0x42, 0xf1, 0x48, 0xc3, 0x57, 0x07, 0xba, 0xcc, 0x70, 0x5c, 0xa5, 0x37, 0x47, 0x92, 0x05, + 0x5c, 0x6b, 0x1c, 0x97, 0x86, 0x97, 0xf3, 0x70, 0x3d, 0x0d, 0xb6, 0x82, 0x98, 0x62, 0x5a, 0x4f, + 0x1a, 0x70, 0x7d, 0xfc, 0x7b, 0x05, 0x9d, 0x4a, 0x52, 0x64, 0xb8, 0x32, 0x82, 0x5b, 0xe9, 0xd4, + 0x3d, 0x1c, 0xcc, 0x75, 0x0e, 0xf3, 0x06, 0x5e, 0x29, 0x80, 0xa9, 0xd7, 0x83, 0x43, 0x3c, 0x02, + 0x6b, 0x99, 0x7d, 0xfc, 0x81, 0x82, 0xbe, 0x10, 0x5b, 0x7c, 0xb0, 0xbd, 0x87, 0x5f, 0x1f, 0xe8, + 0x39, 0x7e, 0x46, 0x97, 0x06, 0x67, 0x3c, 0xf3, 0x7a, 0x56, 0xbf, 0xca, 0xd1, 0x5d, 0xc7, 0x95, + 0x22, 0x74, 0x76, 0xc3, 0xd7, 0x7a, 0xe1, 0xeb, 0xbc, 0x8f, 0xff, 0x08, 0x45, 0x16, 0x4f, 0xdf, + 0x82, 0x22, 0x27, 0x68, 0xbf, 0x82, 0xec, 0x25, 0xa9, 0x38, 0xf5, 0x6d, 0x8e, 0xef, 0x36, 0xbe, + 0x35, 0x10, 0x9f, 0x78, 0xa0, 0x25, 0x8b, 0xac, 0xf5, 0xa4, 0x97, 0x5c, 0x5c, 0xf2, 0x98, 0x22, + 0x2c, 0x28, 0x79, 0x86, 0x4b, 0x3c, 0x1c, 0xe8, 0xe2, 0x92, 0x03, 0x3c, 0x28, 0x79, 0xc4, 0x52, + 0xc6, 0x25, 0x8f, 0xc8, 0x88, 0xa3, 0x96, 0x3c, 0xc3, 0x6a, 0x8c, 0x50, 0xf2, 0x30, 0x79, 0xc9, + 0x92, 0xff, 0x44, 0x41, 0xb3, 0x12, 0x1b, 0x88, 0x07, 0xa7, 0x24, 0xcb, 0x4b, 0x96, 0xae, 0x8d, + 0x26, 0x0c, 0x10, 0x97, 0x38, 0x44, 0x15, 0x5f, 0xcc, 0x83, 0xd8, 0xb2, 0x3c, 0x1f, 0xba, 0xd2, + 0xc3, 0xbf, 0x02, 0x50, 0xc0, 0x74, 0x15, 0x80, 0x4a, 0xf2, 0x83, 0x05, 0xa0, 0x52, 0xe4, 0xd9, + 0xf0, 0xbc, 0x71, 0x50, 0x22, 0x6f, 0x5e, 0x6a, 0xe0, 0xfc, 0x4d, 0x41, 0xaf, 0xe4, 0xf2, 0x82, + 0x78, 0x6d, 0x14, 0xff, 0x19, 0x1e, 0xf1, 0x90, 0xb0, 0x37, 0x38, 0xec, 0x5b, 0x78, 0xbd, 0x08, + 0x76, 0xd0, 0x8d, 0xd1, 0xf0, 0x49, 0xcc, 0xa1, 0x9f, 0x29, 0x68, 0x2e, 0x7a, 0xa0, 0x8d, 0xdc, + 0x93, 0x6f, 0x0c, 0x14, 0x4a, 0xd3, 0x61, 0x23, 0x8c, 0x72, 0x78, 0x43, 0x26, 0x3b, 0xf2, 0x1f, + 0x21, 0x53, 0x90, 0xa6, 0xa0, 0xf0, 0xf5, 0xc1, 0xe7, 0x5c, 0x3e, 0x61, 0x56, 0x5a, 0x39, 0x84, + 0x06, 0xa0, 0xbe, 0xcf, 0x51, 0xef, 0xe0, 0xad, 0xdc, 0x83, 0x51, 0x3c, 0xcb, 0x1a, 0xcc, 0xd5, + 0x89, 0xd0, 0xd3, 0x7a, 0xe1, 0xa3, 0xb2, 0xaf, 0xf5, 0x32, 0x04, 0x5c, 0x1f, 0xff, 0x53, 0x41, + 0x67, 0xd2, 0xb4, 0xd0, 0x90, 0x40, 0x06, 0xb0, 0x63, 0x43, 0x02, 0x19, 0xc4, 0x39, 0xa9, 0x7b, + 0x3c, 0x90, 0x07, 0xf8, 0x5e, 0x5e, 0x20, 0xcf, 0xb9, 0x96, 0x2e, 0xfd, 0xbf, 0x60, 0x2f, 0xe4, + 0xd4, 0xfa, 0xe9, 0xa9, 0x2b, 0xd1, 0x63, 0x7d, 0xfc, 0x5b, 0x05, 0xcd, 0x44, 0x5d, 0x83, 0xdf, + 0x18, 0x3a, 0x40, 0xe5, 0xe7, 0x78, 0xe9, 0xea, 0x28, 0xa2, 0xa3, 0x74, 0x77, 0xdc, 0x39, 0x5a, + 0x4f, 0xe2, 0x2f, 0xfa, 0xe1, 0x37, 0xb1, 0x3f, 0x3f, 0x50, 0xd0, 0x4c, 0xc4, 0xe6, 0x0c, 0xc1, + 0x99, 0xa6, 0xa3, 0x86, 0xe0, 0xcc, 0x90, 0x43, 0xea, 0x4d, 0x8e, 0xb3, 0x82, 0xaf, 0x0d, 0xdc, + 0x85, 0x39, 0x38, 0xf1, 0x6f, 0x14, 0x74, 0x3a, 0xc5, 0x8c, 0x60, 0xad, 0x38, 0x3b, 0x09, 0xba, + 0xa7, 0x74, 0x7d, 0x74, 0x05, 0x00, 0xbb, 0xcc, 0xc1, 0x5e, 0xc1, 0x5f, 0x29, 0xd8, 0x8e, 0xc0, + 0x0e, 0xfd, 0x3d, 0x64, 0x05, 0x92, 0xac, 0xc7, 0x90, 0x33, 0x36, 0x97, 0x86, 0x29, 0x69, 0x23, + 0xcb, 0x03, 0xce, 0x7b, 0x1c, 0xe7, 0x36, 0xbe, 0x5b, 0xb0, 0x01, 0x21, 0xb5, 0xb9, 0xdb, 0x2f, + 0xa4, 0x74, 0xfa, 0xc1, 0x51, 0x72, 0x3a, 0xc5, 0x97, 0x0c, 0xb9, 0xd7, 0x64, 0xb8, 0x98, 0x21, + 0x57, 0x84, 0x2c, 0x01, 0x33, 0xbc, 0x1f, 0x00, 0x3a, 0xdc, 0x0e, 0x22, 0x82, 0xa7, 0x8f, 0x7f, + 0xa8, 0xa0, 0x39, 0x99, 0xe0, 0xc0, 0x83, 0x9f, 0x1a, 0x49, 0x86, 0xa6, 0xb4, 0x54, 0x2c, 0x08, + 0xc8, 0xbe, 0xcc, 0x91, 0x95, 0xf1, 0xf9, 0xdc, 0x4e, 0x65, 0xc6, 0xbe, 0xde, 0xa0, 0x14, 0xff, + 0x19, 0x3a, 0x53, 0xe2, 0x2d, 0x0a, 0x3a, 0x33, 0xcb, 0x90, 0x14, 0x74, 0x66, 0x0e, 0x25, 0xa2, + 0xde, 0xe2, 0xe0, 0xd6, 0xf0, 0x8d, 0xa2, 0xeb, 0x2a, 0xa7, 0x3f, 0x52, 0x07, 0xf1, 0x5f, 0xc2, + 0x3e, 0x4d, 0x32, 0x19, 0x43, 0xfa, 0x34, 0x97, 0x32, 0x19, 0xd2, 0xa7, 0xf9, 0x14, 0x89, 0xfa, + 0x75, 0x8e, 0xfa, 0x26, 0x5e, 0xcd, 0x43, 0x6d, 0x79, 0xe2, 0x39, 0xab, 0x03, 0x6d, 0x92, 0x04, + 0xbd, 0x59, 0xfd, 0xe8, 0x45, 0x59, 0xf9, 0xf8, 0x45, 0x59, 0xf9, 0xcf, 0x8b, 0xb2, 0xf2, 0xe3, + 0x97, 0xe5, 0x63, 0x1f, 0xbf, 0x2c, 0x1f, 0xfb, 0xf7, 0xcb, 0xf2, 0xb1, 0x27, 0x9a, 0xf4, 0xe0, + 0xad, 0xdb, 0xf5, 0x65, 0xe3, 0x29, 0xb1, 0x6c, 0xd9, 0xc3, 0xbb, 0xc9, 0x3f, 0xc4, 0xa8, 0x4f, + 0xf1, 0x3f, 0xb2, 0xb8, 0xf1, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf4, 0xd1, 0x6a, 0xa9, 0xc2, + 0x22, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1932,6 +2136,10 @@ type QueryClient interface { QueryPolicyById(ctx context.Context, in *QueryPolicyByIdRequest, opts ...grpc.CallOption) (*QueryPolicyByIdResponse, error) // Queries lock fee for storing an object QueryLockFee(ctx context.Context, in *QueryLockFeeRequest, opts ...grpc.CallOption) (*QueryLockFeeResponse, error) + // Queries a bucket extra info (with gvg bindings and price time) with specify name. + HeadBucketExtra(ctx context.Context, in *QueryHeadBucketExtraRequest, opts ...grpc.CallOption) (*QueryHeadBucketExtraResponse, error) + // Queries whether read and storage prices changed for the bucket. + QueryIsPriceChanged(ctx context.Context, in *QueryIsPriceChangedRequest, opts ...grpc.CallOption) (*QueryIsPriceChangedResponse, error) } type queryClient struct { @@ -2122,6 +2330,24 @@ func (c *queryClient) QueryLockFee(ctx context.Context, in *QueryLockFeeRequest, return out, nil } +func (c *queryClient) HeadBucketExtra(ctx context.Context, in *QueryHeadBucketExtraRequest, opts ...grpc.CallOption) (*QueryHeadBucketExtraResponse, error) { + out := new(QueryHeadBucketExtraResponse) + err := c.cc.Invoke(ctx, "/greenfield.storage.Query/HeadBucketExtra", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) QueryIsPriceChanged(ctx context.Context, in *QueryIsPriceChangedRequest, opts ...grpc.CallOption) (*QueryIsPriceChangedResponse, error) { + out := new(QueryIsPriceChangedResponse) + err := c.cc.Invoke(ctx, "/greenfield.storage.Query/QueryIsPriceChanged", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Parameters queries the parameters of the module. @@ -2164,6 +2390,10 @@ type QueryServer interface { QueryPolicyById(context.Context, *QueryPolicyByIdRequest) (*QueryPolicyByIdResponse, error) // Queries lock fee for storing an object QueryLockFee(context.Context, *QueryLockFeeRequest) (*QueryLockFeeResponse, error) + // Queries a bucket extra info (with gvg bindings and price time) with specify name. + HeadBucketExtra(context.Context, *QueryHeadBucketExtraRequest) (*QueryHeadBucketExtraResponse, error) + // Queries whether read and storage prices changed for the bucket. + QueryIsPriceChanged(context.Context, *QueryIsPriceChangedRequest) (*QueryIsPriceChangedResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -2230,6 +2460,12 @@ func (*UnimplementedQueryServer) QueryPolicyById(ctx context.Context, req *Query func (*UnimplementedQueryServer) QueryLockFee(ctx context.Context, req *QueryLockFeeRequest) (*QueryLockFeeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method QueryLockFee not implemented") } +func (*UnimplementedQueryServer) HeadBucketExtra(ctx context.Context, req *QueryHeadBucketExtraRequest) (*QueryHeadBucketExtraResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HeadBucketExtra not implemented") +} +func (*UnimplementedQueryServer) QueryIsPriceChanged(ctx context.Context, req *QueryIsPriceChangedRequest) (*QueryIsPriceChangedResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryIsPriceChanged not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -2595,6 +2831,42 @@ func _Query_QueryLockFee_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _Query_HeadBucketExtra_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryHeadBucketExtraRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).HeadBucketExtra(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/greenfield.storage.Query/HeadBucketExtra", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).HeadBucketExtra(ctx, req.(*QueryHeadBucketExtraRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_QueryIsPriceChanged_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryIsPriceChangedRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).QueryIsPriceChanged(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/greenfield.storage.Query/QueryIsPriceChanged", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).QueryIsPriceChanged(ctx, req.(*QueryIsPriceChangedRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "greenfield.storage.Query", HandlerType: (*QueryServer)(nil), @@ -2679,6 +2951,14 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "QueryLockFee", Handler: _Query_QueryLockFee_Handler, }, + { + MethodName: "HeadBucketExtra", + Handler: _Query_HeadBucketExtra_Handler, + }, + { + MethodName: "QueryIsPriceChanged", + Handler: _Query_QueryIsPriceChanged_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "greenfield/storage/query.proto", @@ -3963,89 +4243,277 @@ func (m *QueryLockFeeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { - offset -= sovQuery(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *QueryParamsRequest) Size() (n int) { - if m == nil { - return 0 +func (m *QueryHeadBucketExtraRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - var l int - _ = l - return n + return dAtA[:n], nil } -func (m *QueryParamsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.Params.Size() - n += 1 + l + sovQuery(uint64(l)) - return n +func (m *QueryHeadBucketExtraRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryParamsByTimestampRequest) Size() (n int) { - if m == nil { - return 0 - } +func (m *QueryHeadBucketExtraRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - if m.Timestamp != 0 { - n += 1 + sovQuery(uint64(m.Timestamp)) + if len(m.BucketName) > 0 { + i -= len(m.BucketName) + copy(dAtA[i:], m.BucketName) + i = encodeVarintQuery(dAtA, i, uint64(len(m.BucketName))) + i-- + dAtA[i] = 0xa } - return n + return len(dAtA) - i, nil } -func (m *QueryParamsByTimestampResponse) Size() (n int) { - if m == nil { - return 0 +func (m *QueryHeadBucketExtraResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - var l int - _ = l - l = m.Params.Size() - n += 1 + l + sovQuery(uint64(l)) - return n + return dAtA[:n], nil } -func (m *QueryHeadBucketRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.BucketName) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n +func (m *QueryHeadBucketExtraResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryHeadBucketByIdRequest) Size() (n int) { - if m == nil { - return 0 - } +func (m *QueryHeadBucketExtraResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - l = len(m.BucketId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) + if m.ExtraInfo != nil { + { + size, err := m.ExtraInfo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa } - return n + return len(dAtA) - i, nil } -func (m *QueryHeadBucketResponse) Size() (n int) { - if m == nil { - return 0 +func (m *QueryIsPriceChangedRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryIsPriceChangedRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryIsPriceChangedRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.BucketName) > 0 { + i -= len(m.BucketName) + copy(dAtA[i:], m.BucketName) + i = encodeVarintQuery(dAtA, i, uint64(len(m.BucketName))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryIsPriceChangedResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryIsPriceChangedResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryIsPriceChangedResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.NewSecondaryStorePrice.Size() + i -= size + if _, err := m.NewSecondaryStorePrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + { + size := m.NewPrimaryStorePrice.Size() + i -= size + if _, err := m.NewPrimaryStorePrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + { + size := m.NewReadPrice.Size() + i -= size + if _, err := m.NewReadPrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + { + size := m.CurrentSecondaryStorePrice.Size() + i -= size + if _, err := m.CurrentSecondaryStorePrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size := m.CurrentPrimaryStorePrice.Size() + i -= size + if _, err := m.CurrentPrimaryStorePrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size := m.CurrentReadPrice.Size() + i -= size + if _, err := m.CurrentReadPrice.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.Changed { + i-- + if m.Changed { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryParamsByTimestampRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Timestamp != 0 { + n += 1 + sovQuery(uint64(m.Timestamp)) + } + return n +} + +func (m *QueryParamsByTimestampResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryHeadBucketRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.BucketName) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryHeadBucketByIdRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.BucketId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryHeadBucketResponse) Size() (n int) { + if m == nil { + return 0 } var l int _ = l @@ -4492,6 +4960,69 @@ func (m *QueryLockFeeResponse) Size() (n int) { return n } +func (m *QueryHeadBucketExtraRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.BucketName) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryHeadBucketExtraResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ExtraInfo != nil { + l = m.ExtraInfo.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryIsPriceChangedRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.BucketName) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryIsPriceChangedResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Changed { + n += 2 + } + l = m.CurrentReadPrice.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.CurrentPrimaryStorePrice.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.CurrentSecondaryStorePrice.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.NewReadPrice.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.NewPrimaryStorePrice.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.NewSecondaryStorePrice.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -7929,6 +8460,530 @@ func (m *QueryLockFeeResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryHeadBucketExtraRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryHeadBucketExtraRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryHeadBucketExtraRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BucketName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BucketName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryHeadBucketExtraResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryHeadBucketExtraResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryHeadBucketExtraResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExtraInfo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ExtraInfo == nil { + m.ExtraInfo = &InternalBucketInfo{} + } + if err := m.ExtraInfo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryIsPriceChangedRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryIsPriceChangedRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryIsPriceChangedRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BucketName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BucketName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryIsPriceChangedResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryIsPriceChangedResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryIsPriceChangedResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Changed", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Changed = bool(v != 0) + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentReadPrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.CurrentReadPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentPrimaryStorePrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.CurrentPrimaryStorePrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentSecondaryStorePrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.CurrentSecondaryStorePrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewReadPrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.NewReadPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewPrimaryStorePrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.NewPrimaryStorePrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewSecondaryStorePrice", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.NewSecondaryStorePrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/storage/types/query.pb.gw.go b/x/storage/types/query.pb.gw.go index 8b05ed2f9..f66bbd84e 100644 --- a/x/storage/types/query.pb.gw.go +++ b/x/storage/types/query.pb.gw.go @@ -1234,6 +1234,114 @@ func local_request_Query_QueryLockFee_0(ctx context.Context, marshaler runtime.M } +func request_Query_HeadBucketExtra_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryHeadBucketExtraRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["bucket_name"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bucket_name") + } + + protoReq.BucketName, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bucket_name", err) + } + + msg, err := client.HeadBucketExtra(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_HeadBucketExtra_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryHeadBucketExtraRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["bucket_name"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bucket_name") + } + + protoReq.BucketName, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bucket_name", err) + } + + msg, err := server.HeadBucketExtra(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_QueryIsPriceChanged_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryIsPriceChangedRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["bucket_name"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bucket_name") + } + + protoReq.BucketName, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bucket_name", err) + } + + msg, err := client.QueryIsPriceChanged(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_QueryIsPriceChanged_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryIsPriceChangedRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["bucket_name"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "bucket_name") + } + + protoReq.BucketName, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "bucket_name", err) + } + + msg, err := server.QueryIsPriceChanged(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -1700,6 +1808,52 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_HeadBucketExtra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_HeadBucketExtra_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_HeadBucketExtra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_QueryIsPriceChanged_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_QueryIsPriceChanged_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryIsPriceChanged_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -2141,6 +2295,46 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_HeadBucketExtra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_HeadBucketExtra_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_HeadBucketExtra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_QueryIsPriceChanged_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_QueryIsPriceChanged_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryIsPriceChanged_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -2184,6 +2378,10 @@ var ( pattern_Query_QueryPolicyById_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"greenfield", "storage", "policy_by_id", "policy_id"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_QueryLockFee_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"greenfield", "storage", "lock_fee"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_HeadBucketExtra_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"greenfield", "storage", "head_bucket_extra", "bucket_name"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_QueryIsPriceChanged_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"greenfield", "storage", "is_price_changed", "bucket_name"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -2226,4 +2424,8 @@ var ( forward_Query_QueryPolicyById_0 = runtime.ForwardResponseMessage forward_Query_QueryLockFee_0 = runtime.ForwardResponseMessage + + forward_Query_HeadBucketExtra_0 = runtime.ForwardResponseMessage + + forward_Query_QueryIsPriceChanged_0 = runtime.ForwardResponseMessage ) From 44e4e405986a986c52b422a64e84f82c06f7799b Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Fri, 14 Jul 2023 16:43:52 +0800 Subject: [PATCH 04/33] add some tests related to virtual group --- e2e/tests/payment_test.go | 178 +++++++++++++++++++++++++- x/virtualgroup/keeper/payment_test.go | 130 +++++++++++++++++++ 2 files changed, 302 insertions(+), 6 deletions(-) create mode 100644 x/virtualgroup/keeper/payment_test.go diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index de8e2fbf4..11c045ce0 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -814,7 +814,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InBlocks() { s.updateParams(params) } -func (s *PaymentTestSuite) TestDeleteBucketWithReadQuota() { +func (s *PaymentTestSuite) TestStorageBill_DeleteBucket_WithReadQuota() { var err error ctx := context.Background() sp := s.StorageProviders[0] @@ -860,7 +860,7 @@ func (s *PaymentTestSuite) TestDeleteBucketWithReadQuota() { s.Require().Equal(streamRecordsAfterDelete.User.NetflowRate.String(), "0") } -func (s *PaymentTestSuite) TestStorageSmoke() { +func (s *PaymentTestSuite) TestStorageBill_Smoke() { var err error ctx := context.Background() sp := s.StorageProviders[0] @@ -1073,9 +1073,9 @@ func (s *PaymentTestSuite) TestStorageSmoke() { s.T().Logf("deleteObjectSimRes %v", deleteObjectSimRes.Result) } -// TestForceDeletion_DeleteAfterPriceChange will cover the following case: +// TestStorageBill_DeleteObjectBucket_WithPriceChange will cover the following case: // create an object, sp increase the price a lot, the object can be force deleted even the object's own has no enough balance. -func (s *PaymentTestSuite) TestForceDeletion_AfterPriceChange() { +func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() { ctx := context.Background() // set storage price @@ -1540,6 +1540,172 @@ func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) } +func (s *PaymentTestSuite) TestVirtualGroup_Settle() { + var err error + ctx := context.Background() + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + bucketName := s.createBucket(user, 1024) + _, _, objectName, objectId, checksums, _ := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName, objectId, checksums) + + // sleep seconds + time.Sleep(3 * time.Second) + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // settle gvg family + msgSettle := virtualgrouptypes.MsgSettle{ + StorageProvider: sp.FundingKey.GetAddr().String(), + GlobalVirtualGroupFamilyId: family.Id, + } + s.SendTxBlock(sp.FundingKey, &msgSettle) + + // settle gvg + var secondarySp *core.StorageProvider + for _, sp := range s.StorageProviders { + for _, id := range gvg.SecondarySpIds { + if sp.Info.Id == id { + secondarySp = &sp + break + } + } + } + msgSettle = virtualgrouptypes.MsgSettle{ + StorageProvider: secondarySp.FundingKey.GetAddr().String(), + GlobalVirtualGroupFamilyId: 0, + GlobalVirtualGroupIds: []uint32{gvg.Id}, + } + s.SendTxBlock(secondarySp.FundingKey, &msgSettle) + + // assertions - balance has been checked in other tests in virtual group + streamRecordsAfter := s.getStreamRecords(streamAddresses) + + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) +} + +func (s *PaymentTestSuite) TestVirtualGroup_SwapOut() { + user := s.GenAndChargeAccounts(1, 1000000)[0] + // create a new storage provider + sp := s.BaseSuite.CreateNewStorageProvider() + s.T().Logf("new SP Info: %s", sp.Info.String()) + + successorSp := s.StorageProviders[0] + + // create a new gvg group for this storage provider + var secondarySPIDs []uint32 + for _, ssp := range s.StorageProviders { + if ssp.Info.Id != successorSp.Info.Id { + secondarySPIDs = append(secondarySPIDs, ssp.Info.Id) + } + if len(secondarySPIDs) == 6 { + break + } + } + + gvgID, familyID := s.BaseSuite.CreateGlobalVirtualGroup(sp, 0, secondarySPIDs, 1) + + // create object + s.BaseSuite.CreateObject(user, sp, gvgID, storagetestutils.GenRandomBucketName(), storagetestutils.GenRandomObjectName()) + + // Create another gvg contains this new sp + anotherSP := s.StorageProviders[1] + var anotherSecondarySPIDs []uint32 + for _, ssp := range s.StorageProviders { + if ssp.Info.Id != successorSp.Info.Id && ssp.Info.Id != anotherSP.Info.Id { + anotherSecondarySPIDs = append(anotherSecondarySPIDs, ssp.Info.Id) + } + if len(anotherSecondarySPIDs) == 5 { + break + } + } + anotherSecondarySPIDs = append(anotherSecondarySPIDs, sp.Info.Id) + + familyResp, err := s.Client.GlobalVirtualGroupFamilies( + context.Background(), + &virtualgrouptypes.QueryGlobalVirtualGroupFamiliesRequest{StorageProviderId: anotherSP.Info.Id}) + s.Require().NoError(err) + anotherSPsFamilies := familyResp.GlobalVirtualGroupFamilies + s.Require().Greater(len(anotherSPsFamilies), 0) + anotherGVGID, _ := s.BaseSuite.CreateGlobalVirtualGroup(&anotherSP, anotherSPsFamilies[0].Id, anotherSecondarySPIDs, 1) + + gvgResp, err := s.Client.GlobalVirtualGroup( + context.Background(), + &virtualgrouptypes.QueryGlobalVirtualGroupRequest{GlobalVirtualGroupId: anotherGVGID}) + s.Require().NoError(err) + + streamAddresses := []string{ + user.GetAddr().String(), + anotherSPsFamilies[0].VirtualPaymentAddress, + gvgResp.GlobalVirtualGroup.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // sp exit + s.SendTxBlock(sp.OperatorKey, &virtualgrouptypes.MsgStorageProviderExit{ + StorageProvider: sp.OperatorKey.GetAddr().String(), + }) + + spResp, err := s.Client.StorageProvider(context.Background(), &sptypes.QueryStorageProviderRequest{Id: sp.Info.Id}) + s.Require().NoError(err) + s.Require().Equal(spResp.StorageProvider.Status, sptypes.STATUS_GRACEFUL_EXITING) + + // swap out, as primary sp + msgSwapOut := virtualgrouptypes.NewMsgSwapOut(sp.OperatorKey.GetAddr(), familyID, nil, successorSp.Info.Id) + msgSwapOut.SuccessorSpApproval = &common.Approval{ExpiredHeight: math.MaxUint} + msgSwapOut.SuccessorSpApproval.Sig, err = successorSp.ApprovalKey.Sign(msgSwapOut.GetApprovalBytes()) + s.Require().NoError(err) + s.SendTxBlock(sp.OperatorKey, msgSwapOut) + + msgCompleteSwapOut := virtualgrouptypes.NewMsgCompleteSwapOut(successorSp.OperatorKey.GetAddr(), familyID, nil) + s.Require().NoError(err) + s.SendTxBlock(successorSp.OperatorKey, msgCompleteSwapOut) + + // swap out again, as secondary sp + msgSwapOut2 := virtualgrouptypes.NewMsgSwapOut(sp.OperatorKey.GetAddr(), 0, []uint32{anotherGVGID}, successorSp.Info.Id) + msgSwapOut2.SuccessorSpApproval = &common.Approval{ExpiredHeight: math.MaxUint} + msgSwapOut2.SuccessorSpApproval.Sig, err = successorSp.ApprovalKey.Sign(msgSwapOut2.GetApprovalBytes()) + s.Require().NoError(err) + s.SendTxBlock(sp.OperatorKey, msgSwapOut2) + + // complete swap out + msgCompleteSwapOut2 := virtualgrouptypes.NewMsgCompleteSwapOut(successorSp.OperatorKey.GetAddr(), 0, []uint32{anotherGVGID}) + s.SendTxBlock(successorSp.OperatorKey, msgCompleteSwapOut2) + + // sp complete exit success + s.SendTxBlock( + sp.OperatorKey, + &virtualgrouptypes.MsgCompleteStorageProviderExit{StorageProvider: sp.OperatorKey.GetAddr().String()}, + ) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) +} + func TestPaymentTestSuite(t *testing.T) { suite.Run(t, new(PaymentTestSuite)) } @@ -2021,9 +2187,9 @@ func (s *PaymentTestSuite) deleteBucket(user keys.KeyManager, bucketName string) s.SendTxBlock(user, msgDeleteObject) // HeadObject - queryHeadBucektRequest := storagetypes.QueryHeadBucketRequest{ + queryHeadBucketRequest := storagetypes.QueryHeadBucketRequest{ BucketName: bucketName, } - _, err := s.Client.HeadBucket(context.Background(), &queryHeadBucektRequest) + _, err := s.Client.HeadBucket(context.Background(), &queryHeadBucketRequest) return err } diff --git a/x/virtualgroup/keeper/payment_test.go b/x/virtualgroup/keeper/payment_test.go new file mode 100644 index 000000000..be104372a --- /dev/null +++ b/x/virtualgroup/keeper/payment_test.go @@ -0,0 +1,130 @@ +package keeper_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" + + "cosmossdk.io/math" + + "github.com/bnb-chain/greenfield/testutil/sample" + "github.com/bnb-chain/greenfield/x/challenge" + sptypes "github.com/bnb-chain/greenfield/x/sp/types" + + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/suite" + + "github.com/bnb-chain/greenfield/x/virtualgroup/keeper" + "github.com/bnb-chain/greenfield/x/virtualgroup/types" +) + +type TestSuite struct { + suite.Suite + + cdc codec.Codec + virtualgroupKeeper *keeper.Keeper + + bankKeeper *types.MockBankKeeper + accountKeeper *types.MockAccountKeeper + spKeeper *types.MockSpKeeper + paymentKeeper *types.MockPaymentKeeper + + ctx sdk.Context + queryClient types.QueryClient + msgServer types.MsgServer +} + +func (s *TestSuite) SetupTest() { + encCfg := moduletestutil.MakeTestEncodingConfig(challenge.AppModuleBasic{}) + key := storetypes.NewKVStoreKey(types.StoreKey) + testCtx := testutil.DefaultContextWithDB(s.T(), key, storetypes.NewTransientStoreKey("transient_test")) + + ctrl := gomock.NewController(s.T()) + + bankKeeper := types.NewMockBankKeeper(ctrl) + accountKeeper := types.NewMockAccountKeeper(ctrl) + spKeeper := types.NewMockSpKeeper(ctrl) + paymentKeeper := types.NewMockPaymentKeeper(ctrl) + + s.ctx = testCtx.Ctx + s.virtualgroupKeeper = keeper.NewKeeper( + encCfg.Codec, + key, + key, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + spKeeper, + accountKeeper, + bankKeeper, + paymentKeeper, + ) + + s.cdc = encCfg.Codec + s.bankKeeper = bankKeeper + s.accountKeeper = accountKeeper + s.spKeeper = spKeeper + s.paymentKeeper = paymentKeeper + + err := s.virtualgroupKeeper.SetParams(s.ctx, types.DefaultParams()) + s.Require().NoError(err) +} + +func TestTestSuite(t *testing.T) { + suite.Run(t, new(TestSuite)) +} + +func (s *TestSuite) TestSettleAndDistributeGVGFamily() { + sp := &sptypes.StorageProvider{Id: 1, FundingAddress: sample.RandAccAddress().String()} + family := &types.GlobalVirtualGroupFamily{Id: 1, VirtualPaymentAddress: sample.RandAccAddress().String()} + + s.paymentKeeper.EXPECT().QueryDynamicBalance(gomock.Any(), gomock.Any()). + Return(math.ZeroInt(), nil) + err := s.virtualgroupKeeper.SettleAndDistributeGVGFamily(s.ctx, sp, family) + require.NoError(s.T(), err) + + s.paymentKeeper.EXPECT().QueryDynamicBalance(gomock.Any(), gomock.Any()). + Return(math.ZeroInt(), errors.New("error")) + err = s.virtualgroupKeeper.SettleAndDistributeGVGFamily(s.ctx, sp, family) + require.Error(s.T(), err) + + s.paymentKeeper.EXPECT().QueryDynamicBalance(gomock.Any(), gomock.Any()). + Return(math.NewInt(1024), nil) + s.paymentKeeper.EXPECT().Withdraw(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(nil) + err = s.virtualgroupKeeper.SettleAndDistributeGVGFamily(s.ctx, sp, family) + require.NoError(s.T(), err) +} + +func (s *TestSuite) TestSettleAndDistributeGVG() { + gvg := &types.GlobalVirtualGroup{Id: 1, + VirtualPaymentAddress: sample.RandAccAddress().String(), + SecondarySpIds: []uint32{3, 6, 9}} + + s.paymentKeeper.EXPECT().QueryDynamicBalance(gomock.Any(), gomock.Any()). + Return(math.ZeroInt(), nil) + err := s.virtualgroupKeeper.SettleAndDistributeGVG(s.ctx, gvg) + require.NoError(s.T(), err) + + s.paymentKeeper.EXPECT().QueryDynamicBalance(gomock.Any(), gomock.Any()). + Return(math.ZeroInt(), errors.New("error")) + err = s.virtualgroupKeeper.SettleAndDistributeGVG(s.ctx, gvg) + require.Error(s.T(), err) + + s.paymentKeeper.EXPECT().QueryDynamicBalance(gomock.Any(), gomock.Any()). + Return(math.NewInt(1024), nil).AnyTimes() + s.paymentKeeper.EXPECT().Withdraw(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(nil).AnyTimes() + + sp := &sptypes.StorageProvider{Id: 1, FundingAddress: sample.RandAccAddress().String()} + s.spKeeper.EXPECT().GetStorageProvider(gomock.Any(), gomock.Any()). + Return(sp, true).AnyTimes() + err = s.virtualgroupKeeper.SettleAndDistributeGVG(s.ctx, gvg) + require.NoError(s.T(), err) +} From 47784ff648ed268c850445f4337e334db74ae247 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Fri, 14 Jul 2023 17:00:24 +0800 Subject: [PATCH 05/33] add metrics --- x/payment/keeper/stream_record.go | 3 +++ x/payment/types/types.go | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index 5a75611a1..9e2ccb4fd 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -3,6 +3,8 @@ package keeper import ( "fmt" + "github.com/cosmos/cosmos-sdk/telemetry" + sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/store/prefix" storetypes "github.com/cosmos/cosmos-sdk/store/types" @@ -262,6 +264,7 @@ func (k Keeper) ForceSettle(ctx sdk.Context, streamRecord *types.StreamRecord) e change := types.NewDefaultStreamRecordChangeWithAddr(types.GovernanceAddress).WithStaticBalanceChange(totalBalance) _, err := k.UpdateStreamRecordByAddr(ctx, change) if err != nil { + telemetry.IncrCounter(1, types.GovernanceAddressLackBalanceLabel) return fmt.Errorf("update governance stream record failed: %w", err) } } diff --git a/x/payment/types/types.go b/x/payment/types/types.go index 251b1ba17..64bbfa295 100644 --- a/x/payment/types/types.go +++ b/x/payment/types/types.go @@ -14,3 +14,8 @@ var ( const ( ForceUpdateStreamRecordKey = "force_update_stream_record" ) + +const ( + // GovernanceAddressLackBalanceLabel is the metrics label to notify that the governance account has no enough balance + GovernanceAddressLackBalanceLabel = "governance_address_lack_balance" +) From 32b4d568c1306fdeb25c93a84a0a244ad0d0ed20 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Mon, 17 Jul 2023 09:45:32 +0800 Subject: [PATCH 06/33] fix issues and add tests --- deployment/localup/localup.sh | 2 +- e2e/tests/payment_test.go | 371 +++++++++++++++++++++++++++++- x/payment/keeper/stream_record.go | 2 +- x/payment/types/params.go | 4 + x/storage/keeper/payment.go | 19 +- 5 files changed, 388 insertions(+), 10 deletions(-) diff --git a/deployment/localup/localup.sh b/deployment/localup/localup.sh index 4c314d632..690da86c7 100644 --- a/deployment/localup/localup.sh +++ b/deployment/localup/localup.sh @@ -153,7 +153,7 @@ function generate_genesis() { sed -i -e "s/\"discontinue_deletion_max\": \"10000\"/\"discontinue_deletion_max\": \"1\"/g" ${workspace}/.local/validator${i}/config/genesis.json sed -i -e "s/\"voting_period\": \"30s\"/\"voting_period\": \"10s\"/g" ${workspace}/.local/validator${i}/config/genesis.json #sed -i -e "s/\"community_tax\": \"0.020000000000000000\"/\"community_tax\": \"0\"/g" ${workspace}/.local/validator${i}/config/genesis.json - #sed -i -e "s/log_level = \"info\"/\log_level= \"debug\"/g" ${workspace}/.local/validator${i}/config/config.toml + sed -i -e "s/log_level = \"info\"/\log_level= \"debug\"/g" ${workspace}/.local/validator${i}/config/config.toml done # enable swagger API for validator0 diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 11c045ce0..24d11c0a5 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -168,10 +168,12 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRate // update params params := queryParamsResponse.GetParams() oldReserveTime := params.VersionedParams.ReserveTime + oldForceSettleTime := params.ForcedSettleTime oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) params.VersionedParams.ReserveTime = oldReserveTime / 2 + params.ForcedSettleTime = oldForceSettleTime / 2 params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) s.updateParams(params) @@ -194,6 +196,7 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRate // revert params params.VersionedParams.ReserveTime = oldReserveTime + params.ForcedSettleTime = oldForceSettleTime params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate s.updateParams(params) } @@ -996,6 +999,7 @@ func (s *PaymentTestSuite) TestStorageBill_Smoke() { secondaryStorePrice := queryGetSecondarySpStorePriceByTime.SecondarySpStorePrice.StorePrice chargeSize := s.getChargeSize(queryHeadObjectResponse.ObjectInfo.PayloadSize) expectedChargeRate := primaryStorePrice.Add(secondaryStorePrice.MulInt64(6)).MulInt(sdk.NewIntFromUint64(chargeSize)).TruncateInt() + expectedChargeRate = paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(expectedChargeRate).TruncateInt().Add(expectedChargeRate) expectedLockedBalance := expectedChargeRate.Mul(sdkmath.NewIntFromUint64(paymentParams.Params.VersionedParams.ReserveTime)) streamRecordsAfterCreateObject := s.getStreamRecords(streamAddresses) @@ -1073,9 +1077,9 @@ func (s *PaymentTestSuite) TestStorageBill_Smoke() { s.T().Logf("deleteObjectSimRes %v", deleteObjectSimRes.Result) } -// TestStorageBill_DeleteObjectBucket_WithPriceChange will cover the following case: +// TestStorageBill_ForceDeleteObjectBucket_WithPriceChange will cover the following case: // create an object, sp increase the price a lot, the object can be force deleted even the object's own has no enough balance. -func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() { +func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WithPriceChange() { ctx := context.Background() // set storage price @@ -1170,6 +1174,369 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) } +func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithoutPriceChange() { + var err error + ctx := context.Background() + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // create bucket + bucketName := s.createBucket(user, 256) + + //simulate delete bucket gas + msgDeleteBucket := storagetypes.NewMsgDeleteBucket(user.GetAddr(), bucketName) + simulateResponse := s.SimulateTx(msgDeleteBucket, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + gas := gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))) + s.T().Log("total gas", "gas", gas) + + // create & seal objects + _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName1, objectId1, checksums1) + + // for payment + time.Sleep(2 * time.Second) + + //transfer gas + msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, sdkmath.NewInt(5*types.DecimalGwei)), + )) + simulateResponse = s.SimulateTx(msgSend, user) + gasLimit = simulateResponse.GasInfo.GetGasUsed() + gasPrice, err = sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + gas = gas.Add(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit)))) + s.T().Log("total gas", "gas", gas) + + //delete object gas + msgDeleteObject := storagetypes.NewMsgDeleteObject(user.GetAddr(), bucketName, objectName1) + simulateResponse = s.SimulateTx(msgDeleteObject, user) + gasLimit = simulateResponse.GasInfo.GetGasUsed() + gasPrice, err = sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + gas = gas.Add(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit)))) + s.T().Log("total gas", "gas", gas) + + // transfer out user's balance + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gas)), + ) + s.SendTxBlock(user, msgSend) + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + s.SendTxBlock(user, msgDeleteObject) + s.SendTxBlock(user, msgDeleteBucket) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.NetflowRate, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) +} + +func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() { + var err error + ctx := context.Background() + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // create bucket + bucketName := s.createBucket(user, 256) + + //simulate delete bucket gas + msgDeleteBucket := storagetypes.NewMsgDeleteBucket(user.GetAddr(), bucketName) + simulateResponse := s.SimulateTx(msgDeleteBucket, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + gas := gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))) + s.T().Log("total gas", "gas", gas) + + // create & seal objects + _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName1, objectId1, checksums1) + + // for payment + time.Sleep(2 * time.Second) + + //transfer gas + msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, sdkmath.NewInt(5*types.DecimalGwei)), + )) + simulateResponse = s.SimulateTx(msgSend, user) + gasLimit = simulateResponse.GasInfo.GetGasUsed() + gasPrice, err = sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + gas = gas.Add(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit)))) + s.T().Log("total gas", "gas", gas) + + //delete object gas + msgDeleteObject := storagetypes.NewMsgDeleteObject(user.GetAddr(), bucketName, objectName1) + simulateResponse = s.SimulateTx(msgDeleteObject, user) + gasLimit = simulateResponse.GasInfo.GetGasUsed() + gasPrice, err = sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + gas = gas.Add(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit)))) + s.T().Log("total gas", "gas", gas) + + // transfer out user's balance + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gas)), + ) + s.SendTxBlock(user, msgSend) + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + // sp price changes + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: 0, + }) + s.Require().NoError(err) + s.T().Log("price", priceRes.SpStoragePrice) + + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice.MulInt64(1000), + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + s.SendTxBlock(user, msgDeleteObject) + s.SendTxBlock(user, msgDeleteBucket) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.NetflowRate, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // revert price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) +} + +func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreLessThanReserveTime() { + var err error + ctx := context.Background() + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + queryParamsRequest := paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + s.T().Log("queryParamsResponse", core.YamlString(queryParamsResponse)) + reserveTime := queryParamsResponse.Params.VersionedParams.ReserveTime + + // create bucket + bucketName := s.createBucket(user, 256) + + // create & seal objects + _, _, objectName1, objectId1, checksums1, payloadSize := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName1, objectId1, checksums1) + + headObjectRes, err := s.Client.HeadObject(ctx, &storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + }) + s.Require().NoError(err) + s.T().Log("headObjectRes", headObjectRes) + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + _, _, userRateRead := s.calculateReadRates(sp, bucketName) + _, _, _, userRateStore := s.calculateStorageRates(sp, bucketName, objectName1, payloadSize) + + msgDeleteObject := storagetypes.NewMsgDeleteObject(user.GetAddr(), bucketName, objectName1) + s.SendTxBlock(user, msgDeleteObject) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + + settledTime := streamRecordsAfter.User.CrudTimestamp - streamRecordsBefore.User.CrudTimestamp + timeToPay := int64(reserveTime) + headObjectRes.ObjectInfo.CreateAt - streamRecordsAfter.User.CrudTimestamp + balanceDelta := userRateRead.Add(userRateStore).MulRaw(settledTime).Add(userRateStore.MulRaw(timeToPay)) + + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), userRateStore.Int64()) + userBalanceChange := streamRecordsAfter.User.BufferBalance.Add(streamRecordsAfter.User.StaticBalance). + Sub(streamRecordsBefore.User.BufferBalance.Add(streamRecordsBefore.User.StaticBalance)) + s.Require().Equal(userBalanceChange.Neg().Int64(), balanceDelta.Int64()) + + familyDelta := streamRecordsAfter.GVGFamily.StaticBalance.Sub(streamRecordsBefore.GVGFamily.StaticBalance) + gvgDelta := streamRecordsAfter.GVG.StaticBalance.Sub(streamRecordsBefore.GVG.StaticBalance) + taxPoolDelta := streamRecordsAfter.Tax.StaticBalance.Sub(streamRecordsBefore.Tax.StaticBalance) + s.T().Log("familyDelta", familyDelta, "gvgDelta", gvgDelta, "taxPoolDelta", taxPoolDelta) + s.Require().True(familyDelta.Add(gvgDelta).Add(taxPoolDelta).Int64() >= balanceDelta.Int64()) // could exist other buckets/objects on the gvg & family +} + +func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreMoreThanReserveTime() { + var err error + ctx := context.Background() + sp := s.StorageProviders[0] + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + StorageProviderId: sp.Info.Id, + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + queryParamsRequest := paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + s.T().Log("queryParamsResponse", core.YamlString(queryParamsResponse)) + oldReserveTime := queryParamsResponse.Params.VersionedParams.ReserveTime + oldForceSettleTime := queryParamsResponse.Params.ForcedSettleTime + + params := queryParamsResponse.Params + params.VersionedParams.ReserveTime = 5 + params.ForcedSettleTime = 2 + s.updateParams(params) + + // create bucket + bucketName := s.createBucket(user, 256) + + // create & seal objects + _, _, objectName1, objectId1, checksums1, payloadSize := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName1, objectId1, checksums1) + + headObjectRes, err := s.Client.HeadObject(ctx, &storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + }) + s.Require().NoError(err) + s.T().Log("headObjectRes", headObjectRes) + + time.Sleep(5 * time.Second) + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + balanceBefore := queryBalanceResponse.Balance.Amount + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + _, _, userRateRead := s.calculateReadRates(sp, bucketName) + _, _, _, userRateStore := s.calculateStorageRates(sp, bucketName, objectName1, payloadSize) + + msgDeleteObject := storagetypes.NewMsgDeleteObject(user.GetAddr(), bucketName, objectName1) + simulateResponse := s.SimulateTx(msgDeleteObject, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + gas := gasPrice.Amount.MulRaw(int64(gasLimit)) + + // delete object + s.SendTxBlock(user, msgDeleteObject) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + queryBalanceRequest = banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + balanceAfter := queryBalanceResponse.Balance.Amount + + settledTime := streamRecordsAfter.User.CrudTimestamp - streamRecordsBefore.User.CrudTimestamp + balanceDelta := userRateRead.Add(userRateStore).MulRaw(settledTime) + + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), userRateStore.Int64()) + userBalanceChange := streamRecordsBefore.User.BufferBalance.Add(streamRecordsBefore.User.StaticBalance). + Sub(streamRecordsAfter.User.BufferBalance.Add(streamRecordsAfter.User.StaticBalance)) + userBalanceChange = userBalanceChange.Add(balanceBefore.Sub(balanceAfter)).Sub(gas) + s.Require().Equal(userBalanceChange.Int64(), balanceDelta.Int64()) + + familyDelta := streamRecordsAfter.GVGFamily.StaticBalance.Sub(streamRecordsBefore.GVGFamily.StaticBalance) + gvgDelta := streamRecordsAfter.GVG.StaticBalance.Sub(streamRecordsBefore.GVG.StaticBalance) + taxPoolDelta := streamRecordsAfter.Tax.StaticBalance.Sub(streamRecordsBefore.Tax.StaticBalance) + s.T().Log("familyDelta", familyDelta, "gvgDelta", gvgDelta, "taxPoolDelta", taxPoolDelta) + s.Require().True(familyDelta.Add(gvgDelta).Add(taxPoolDelta).Int64() >= balanceDelta.Int64()) // could exist other buckets/objects on the gvg & family + + // revert params + params = queryParamsResponse.Params + params.VersionedParams.ReserveTime = oldReserveTime + params.ForcedSettleTime = oldForceSettleTime + s.updateParams(params) +} + func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuota() { var err error ctx := context.Background() diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index 9e2ccb4fd..b11eb6955 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -193,7 +193,7 @@ func (k Keeper) UpdateStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe payDuration := streamRecord.StaticBalance.Add(streamRecord.BufferBalance).Quo(streamRecord.NetflowRate.Abs()) if payDuration.LTE(sdkmath.NewIntFromUint64(params.ForcedSettleTime)) { if !forced { - return fmt.Errorf("stream account %s balance not enough, lack of %s BNB", streamRecord.Account, streamRecord.StaticBalance.Abs()) + return fmt.Errorf("stream account %s lacks of %s BNB", streamRecord.Account, streamRecord.StaticBalance.Abs()) } } settleTimestamp = currentTimestamp - int64(params.ForcedSettleTime) + payDuration.Int64() diff --git a/x/payment/types/params.go b/x/payment/types/params.go index 13c9532f8..bc1fb52bd 100644 --- a/x/payment/types/params.go +++ b/x/payment/types/params.go @@ -109,6 +109,10 @@ func (p Params) Validate() error { return err } + if p.VersionedParams.ReserveTime <= p.ForcedSettleTime { + return fmt.Errorf("reserve time must be greater than force settle time") + } + return nil } diff --git a/x/storage/keeper/payment.go b/x/storage/keeper/payment.go index 69eb39670..2eefcea3b 100644 --- a/x/storage/keeper/payment.go +++ b/x/storage/keeper/payment.go @@ -270,8 +270,8 @@ func (k Keeper) ChargeObjectStoreFeeForEarlyDeletion(ctx sdk.Context, bucketInfo primaryRate := price.PrimaryStorePrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() if primaryRate.IsPositive() { primaryTotalFlowRate = primaryRate - err = k.paymentKeeper.Withdraw(ctx, paymentAddr, sdk.MustAccAddressFromHex(gvgFamily.VirtualPaymentAddress), - primaryTotalFlowRate.MulRaw(timeToPay)) + _, err = k.paymentKeeper.UpdateStreamRecordByAddr(ctx, types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(gvgFamily.VirtualPaymentAddress)). + WithStaticBalanceChange(primaryTotalFlowRate.MulRaw(timeToPay))) if err != nil { return fmt.Errorf("fail to pay GVG family: %s", err) } @@ -297,8 +297,8 @@ func (k Keeper) ChargeObjectStoreFeeForEarlyDeletion(ctx sdk.Context, bucketInfo secondaryRate = secondaryRate.MulRaw(int64(len(gvg.SecondarySpIds))) if secondaryRate.IsPositive() { secondaryTotalFlowRate = secondaryTotalFlowRate.Add(secondaryRate) - err = k.paymentKeeper.Withdraw(ctx, paymentAddr, sdk.MustAccAddressFromHex(gvg.VirtualPaymentAddress), - secondaryTotalFlowRate.MulRaw(timeToPay)) + _, err = k.paymentKeeper.UpdateStreamRecordByAddr(ctx, types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(gvg.VirtualPaymentAddress)). + WithStaticBalanceChange(secondaryTotalFlowRate.MulRaw(timeToPay))) if err != nil { return fmt.Errorf("fail to pay GVG: %s", err) } @@ -311,13 +311,20 @@ func (k Keeper) ChargeObjectStoreFeeForEarlyDeletion(ctx sdk.Context, bucketInfo } validatorTaxRate := versionedParams.ValidatorTaxRate.MulInt(primaryTotalFlowRate.Add(secondaryTotalFlowRate)).TruncateInt() if validatorTaxRate.IsPositive() { - err = k.paymentKeeper.Withdraw(ctx, paymentAddr, types.ValidatorTaxPoolAddress, - validatorTaxRate.MulRaw(timeToPay)) + _, err = k.paymentKeeper.UpdateStreamRecordByAddr(ctx, types.NewDefaultStreamRecordChangeWithAddr(types.ValidatorTaxPoolAddress). + WithStaticBalanceChange(validatorTaxRate.MulRaw(timeToPay))) if err != nil { return fmt.Errorf("fail to pay validator: %s", err) } } + total := primaryTotalFlowRate.Add(secondaryTotalFlowRate).Add(validatorTaxRate).MulRaw(timeToPay) + _, err = k.paymentKeeper.UpdateStreamRecordByAddr(ctx, types.NewDefaultStreamRecordChangeWithAddr(paymentAddr). + WithStaticBalanceChange(total.Neg())) + if err != nil { + return fmt.Errorf("fail to substrct from payment account: %s", err) + } + return nil } From fc40bd855ceab4366bc0fe67a80a4d9bea9b7676 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Mon, 17 Jul 2023 10:43:26 +0800 Subject: [PATCH 07/33] fix lint issues --- e2e/tests/payment_test.go | 16 ++++++++-------- x/storage/keeper/payment_test.go | 5 +++-- x/virtualgroup/keeper/payment_test.go | 4 +--- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 24d11c0a5..058128ad8 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -1247,7 +1247,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithoutPriceChange sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gas)), ) s.SendTxBlock(user, msgSend) - queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + _, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) s.Require().NoError(err) s.SendTxBlock(user, msgDeleteObject) @@ -1335,7 +1335,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gas)), ) s.SendTxBlock(user, msgSend) - queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + _, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) s.Require().NoError(err) // sp price changes @@ -1570,7 +1570,7 @@ func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuot queryHeadBucketRequest := storagetypes.QueryHeadBucketRequest{ BucketName: bucketName, } - queryHeadBucketResponse, err := s.Client.HeadBucket(ctx, &queryHeadBucketRequest) + _, err = s.Client.HeadBucket(ctx, &queryHeadBucketRequest) s.Require().NoError(err) // assertions @@ -1587,7 +1587,7 @@ func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuot queryHeadBucketRequest = storagetypes.QueryHeadBucketRequest{ BucketName: bucketName, } - queryHeadBucketResponse, err = s.Client.HeadBucket(ctx, &queryHeadBucketRequest) + queryHeadBucketResponse, err := s.Client.HeadBucket(ctx, &queryHeadBucketRequest) s.Require().NoError(err) // check price and rate calculation @@ -1889,10 +1889,10 @@ func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { time.Sleep(3 * time.Second) - s.deleteObject(user, bucketName1, objectName1) - s.deleteObject(user, bucketName1, objectName2) - s.deleteObject(user, bucketName2, objectName3) - s.deleteObject(user, bucketName2, objectName4) + _ = s.deleteObject(user, bucketName1, objectName1) + _ = s.deleteObject(user, bucketName1, objectName2) + _ = s.deleteObject(user, bucketName2, objectName3) + _ = s.deleteObject(user, bucketName2, objectName4) err = s.deleteBucket(user, bucketName1) s.Require().Error(err) err = s.deleteBucket(user, bucketName2) diff --git a/x/storage/keeper/payment_test.go b/x/storage/keeper/payment_test.go index 4499e016b..f83d970a7 100644 --- a/x/storage/keeper/payment_test.go +++ b/x/storage/keeper/payment_test.go @@ -122,8 +122,9 @@ func (s *TestSuite) TestGetObjectLockFee() { amount, err := s.storageKeeper.GetObjectLockFee(s.ctx, 100, time.Now().Unix(), uint64(payloadSize)) s.Require().NoError(err) secondarySPNum := int64(s.storageKeeper.GetExpectSecondarySPNumForECObject(s.ctx, time.Now().Unix())) - expectedAmount := price.PrimaryStorePrice.Add(price.SecondaryStorePrice.MulInt64(secondarySPNum)). - MulInt64(payloadSize).MulInt64(int64(params.VersionedParams.ReserveTime)).TruncateInt() + spRate := price.PrimaryStorePrice.Add(price.SecondaryStorePrice.MulInt64(secondarySPNum)).MulInt64(payloadSize) + validatorTaxRate := params.VersionedParams.ValidatorTaxRate.MulInt(spRate.TruncateInt()) + expectedAmount := spRate.Add(validatorTaxRate).MulInt64(int64(params.VersionedParams.ReserveTime)).TruncateInt() s.Require().True(amount.Equal(expectedAmount)) } diff --git a/x/virtualgroup/keeper/payment_test.go b/x/virtualgroup/keeper/payment_test.go index be104372a..fef9f7627 100644 --- a/x/virtualgroup/keeper/payment_test.go +++ b/x/virtualgroup/keeper/payment_test.go @@ -37,9 +37,7 @@ type TestSuite struct { spKeeper *types.MockSpKeeper paymentKeeper *types.MockPaymentKeeper - ctx sdk.Context - queryClient types.QueryClient - msgServer types.MsgServer + ctx sdk.Context } func (s *TestSuite) SetupTest() { From aa305c9484205b16d12f7a6b31291e4cfbc641f1 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Mon, 17 Jul 2023 16:58:38 +0800 Subject: [PATCH 08/33] fix force delete buckets with frozen account issue --- app/reconciliation.go | 11 +++ e2e/tests/payment_test.go | 93 +++++++++++++++++++++++++- x/payment/keeper/storage_fee_charge.go | 18 +++-- x/payment/keeper/stream_record.go | 10 ++- 4 files changed, 124 insertions(+), 8 deletions(-) diff --git a/app/reconciliation.go b/app/reconciliation.go index cfc9334fd..1a2d915c4 100644 --- a/app/reconciliation.go +++ b/app/reconciliation.go @@ -3,6 +3,7 @@ package app import ( "bytes" "encoding/binary" + "encoding/json" "fmt" "cosmossdk.io/math" @@ -124,6 +125,9 @@ func (app *App) reconPaymentChanges(ctx sdk.Context, paymentIavl *iavl.Store) bo ctx.Logger().Error("fail to unmarshal stream record", "err", err.Error()) } else { flowCurrent = flowCurrent.Add(sr.NetflowRate) + + j, _ := json.Marshal(sr) + ctx.Logger().Debug("stream_record_current", "stream record", j, "addr", parseAddressFromStreamRecordKey(kBz)) } } @@ -139,6 +143,8 @@ func (app *App) reconPaymentChanges(ctx sdk.Context, paymentIavl *iavl.Store) bo ctx.Logger().Error("fail to unmarshal stream record", "err", err.Error()) } else { flowPre = flowPre.Add(sr.NetflowRate) + j, _ := json.Marshal(sr) + ctx.Logger().Debug("stream_record_previous", "stream record", j, "addr", parseAddressFromStreamRecordKey(kBz)) } } } @@ -196,3 +202,8 @@ func parseAmountFromValue(value []byte) math.Int { } return amount } + +func parseAddressFromStreamRecordKey(key []byte) string { + start := len(StreamRecordKeyPrefix) + return sdk.AccAddress(key[start:]).String() +} diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 058128ad8..532162302 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -636,6 +636,8 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { s.T().Logf("familyStreamRecord %s", core.YamlString(familyStreamRecord)) govStreamRecord := s.getStreamRecord(paymenttypes.GovernanceAddress.String()) s.T().Logf("govStreamRecord %s", core.YamlString(govStreamRecord)) + paymentStreamRecord := s.getStreamRecord(paymentAddr) + s.T().Logf("paymentStreamRecord %s", core.YamlString(paymentStreamRecord)) // wait until settle time retryCount := 0 @@ -672,7 +674,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { s.T().Logf("govStreamRecordAfterSettle %s", core.YamlString(govStreamRecordAfterSettle)) s.Require().NotEqual(govStreamRecordAfterSettle.StaticBalance.String(), govStreamRecord.StaticBalance.String()) govStreamRecordStaticBalanceDelta := govStreamRecordAfterSettle.StaticBalance.Sub(govStreamRecord.StaticBalance) - expectedGovBalanceDelta := userStreamRecord.NetflowRate.Neg().MulRaw(userStreamRecordAfterAutoSettle.CrudTimestamp - userStreamRecord.CrudTimestamp) + expectedGovBalanceDelta := paymentStreamRecord.NetflowRate.Neg().MulRaw(paymentAccountStreamRecordAfterAutoSettle.CrudTimestamp - paymentStreamRecord.CrudTimestamp) s.Require().Equal(expectedGovBalanceDelta.String(), govStreamRecordStaticBalanceDelta.String()) // deposit, balance not enough to resume @@ -1077,6 +1079,95 @@ func (s *PaymentTestSuite) TestStorageBill_Smoke() { s.T().Logf("deleteObjectSimRes %v", deleteObjectSimRes.Result) } +func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WhenPaymentAccountFrozen() { + ctx := context.Background() + user := s.GenAndChargeAccounts(1, 1000000)[0] + sp := s.StorageProviders[0] + + queryParamsRequest := paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + s.T().Log("queryParamsResponse", core.YamlString(queryParamsResponse)) + oldReserveTime := queryParamsResponse.Params.VersionedParams.ReserveTime + oldForceSettleTime := queryParamsResponse.Params.ForcedSettleTime + + params := queryParamsResponse.Params + params.VersionedParams.ReserveTime = 5 + params.ForcedSettleTime = 2 + s.updateParams(params) + + // create bucket + bucketName := s.createBucket(user, 0) + + // create & seal objects + _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName1, objectId1, checksums1) + + _, _, objectName2, objectId2, checksums2, _ := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName2, objectId2, checksums2) + + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)), + )) + + simulateResponse := s.SimulateTx(msgSend, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))))), + ) + s.SendTxBlock(user, msgSend) + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) + + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + + // for freeze account + time.Sleep(5 * time.Second) + userStreamRecord := s.getStreamRecord(user.GetAddr().String()) + s.Require().True(userStreamRecord.Status == paymenttypes.STREAM_ACCOUNT_STATUS_FROZEN) + + // force delete bucket + msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") + txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) + deleteAt := filterDiscontinueBucketEventFromTx(txRes).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, deleteAt) + + if blockTime > deleteAt { + break + } + } + + _, err = s.Client.HeadBucket(ctx, &storagetypes.QueryHeadBucketRequest{BucketName: bucketName}) + s.Require().ErrorContains(err, "No such bucket") + + // revert params + params = queryParamsResponse.Params + params.VersionedParams.ReserveTime = oldReserveTime + params.ForcedSettleTime = oldForceSettleTime + s.updateParams(params) +} + // TestStorageBill_ForceDeleteObjectBucket_WithPriceChange will cover the following case: // create an object, sp increase the price a lot, the object can be force deleted even the object's own has no enough balance. func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WithPriceChange() { diff --git a/x/payment/keeper/storage_fee_charge.go b/x/payment/keeper/storage_fee_charge.go index da215a57e..844b49860 100644 --- a/x/payment/keeper/storage_fee_charge.go +++ b/x/payment/keeper/storage_fee_charge.go @@ -52,8 +52,9 @@ func (k Keeper) ApplyStreamRecordChanges(ctx sdk.Context, streamRecordChanges [] func (k Keeper) ApplyUserFlowsList(ctx sdk.Context, userFlowsList []types.UserFlows) (err error) { userFlowsList = k.MergeUserFlows(userFlowsList) currentTime := ctx.BlockTime().Unix() - var streamRecordChanges []types.StreamRecordChange + for _, userFlows := range userFlowsList { + var streamRecordChanges []types.StreamRecordChange from := userFlows.From streamRecord, found := k.GetStreamRecord(ctx, from) if !found { @@ -91,11 +92,18 @@ func (k Keeper) ApplyUserFlowsList(ctx sdk.Context, userFlowsList []types.UserFl streamRecord.OutFlowCount = uint64(int64(streamRecord.OutFlowCount) + int64(deltaFlowCount)) k.SetStreamRecord(ctx, streamRecord) + + // when the account is frozen, the flows to GVG/GVG family had or will be deducted, + // then should not update the flow rate + // for user's payment account, the frozen flow rate will be updated + if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE { + err = k.ApplyStreamRecordChanges(ctx, streamRecordChanges) + if err != nil { + return fmt.Errorf("apply stream record changes failed: %w", err) + } + } } - err = k.ApplyStreamRecordChanges(ctx, streamRecordChanges) - if err != nil { - return fmt.Errorf("apply stream record changes failed: %w", err) - } + return nil } diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index b11eb6955..9466a8537 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -38,6 +38,9 @@ func (k Keeper) CheckStreamRecord(streamRecord *types.StreamRecord) { if streamRecord.BufferBalance.IsNil() || streamRecord.BufferBalance.IsNegative() { panic(fmt.Sprintf("invalid streamRecord bufferBalance %s", streamRecord.BufferBalance)) } + if streamRecord.NetflowRate.IsNegative() && streamRecord.OutFlowCount == 0 { + panic(fmt.Sprintf("invalid streamRecord netflowRate %s when outFlowCount is zero", streamRecord.NetflowRate)) + } } // SetStreamRecord set a specific streamRecord in the store from its index @@ -112,8 +115,6 @@ func (k Keeper) GetAllStreamRecord(ctx sdk.Context) (list []types.StreamRecord) // it only handles the lock balance change and ignore the other changes(since the streams are already changed and the // accumulated OutFlows are changed outside this function) func (k Keeper) UpdateFrozenStreamRecord(ctx sdk.Context, streamRecord *types.StreamRecord, change *types.StreamRecordChange) error { - currentTimestamp := ctx.BlockTime().Unix() - streamRecord.CrudTimestamp = currentTimestamp // update lock balance if !change.LockBalanceChange.IsZero() { streamRecord.LockBalance = streamRecord.LockBalance.Add(change.LockBalanceChange) @@ -122,6 +123,11 @@ func (k Keeper) UpdateFrozenStreamRecord(ctx sdk.Context, streamRecord *types.St return fmt.Errorf("lock balance can not become negative, current: %s", streamRecord.LockBalance) } } + // update netflow + // when there are object/bucket deletions in end block, the frozen rate should be updated + if !change.RateChange.IsZero() { + streamRecord.FrozenNetflowRate = streamRecord.FrozenNetflowRate.Add(change.RateChange) + } return nil } From 3b89c12ba7618ac40e1e730b490a0bdd14aabd40 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Mon, 17 Jul 2023 21:21:04 +0800 Subject: [PATCH 09/33] fix test issue --- e2e/tests/payment_test.go | 103 ++++++++++---------- x/payment/keeper/storage_fee_charge_test.go | 9 ++ x/storage/keeper/payment_test.go | 2 +- 3 files changed, 61 insertions(+), 53 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index c3e000acc..d828812d6 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -92,12 +92,13 @@ func (s *PaymentTestSuite) TestPaymentAccount() { // create an object, increase the reserve time, seal the object without error. func (s *PaymentTestSuite) TestVersionedParams_SealObjectAfterReserveTimeChange() { ctx := context.Background() + sp := s.PickStorageProvider() queryParamsRequest := paymenttypes.QueryParamsRequest{} queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) s.Require().NoError(err) // create bucket, create object - user, bucketName, objectName, objectId, checksums := s.createBucketAndObject() + user, bucketName, objectName, objectId, checksums := s.createBucketAndObject(sp) // update params params := queryParamsResponse.GetParams() @@ -144,6 +145,7 @@ func (s *PaymentTestSuite) TestVersionedParams_SealObjectAfterReserveTimeChange( // The rate of the validator tax address should be correct. func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRateChange() { ctx := context.Background() + sp := s.PickStorageProvider() queryParamsRequest := paymenttypes.QueryParamsRequest{} queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) s.Require().NoError(err) @@ -160,7 +162,7 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRate s.T().Logf("netflow, validatorTaxPoolRate: %s", validatorTaxPoolRate) // create bucket, create object - user, bucketName, objectName, objectId, checksums := s.createBucketAndObject() + user, bucketName, objectName, objectId, checksums := s.createBucketAndObject(sp) // seal object s.sealObject(bucketName, objectName, objectId, checksums) @@ -205,12 +207,13 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRate // create an object, change the reserve time, the object can be force deleted even the object's own has no enough balance. func (s *PaymentTestSuite) TestVersionedParams_DeleteObjectAfterReserveTimeChange() { ctx := context.Background() + sp := s.PickStorageProvider() queryParamsRequest := paymenttypes.QueryParamsRequest{} queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) s.Require().NoError(err) // create bucket, create object - user, bucketName, objectName, objectId, checksums := s.createBucketAndObject() + user, bucketName, objectName, objectId, checksums := s.createBucketAndObject(sp) // seal object s.sealObject(bucketName, objectName, objectId, checksums) @@ -262,8 +265,6 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteObjectAfterReserveTimeChang s.Require().NoError(err) s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) - sp := s.StorageProviders[0] - // force delete bucket msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) @@ -293,7 +294,7 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteObjectAfterReserveTimeChang func (s *PaymentTestSuite) TestDepositAndResume_InOneBlock() { ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) user := s.GenAndChargeAccounts(1, 1000000)[0] @@ -422,7 +423,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InBlocks() { params = queryParamsResponse.GetParams() s.T().Logf("params: %s", params.String()) - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) user := s.GenAndChargeAccounts(1, 1000000)[0] @@ -544,7 +545,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InBlocks() { func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) user := s.GenAndChargeAccounts(1, 1000000)[0] @@ -722,7 +723,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InBlocks() { params = queryParamsResponse.GetParams() s.T().Logf("params: %s", params.String()) - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) user := s.GenAndChargeAccounts(1, 1000000)[0] @@ -821,7 +822,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InBlocks() { func (s *PaymentTestSuite) TestStorageBill_DeleteBucket_WithReadQuota() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -866,7 +867,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteBucket_WithReadQuota() { func (s *PaymentTestSuite) TestStorageBill_Smoke() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1014,11 +1015,11 @@ func (s *PaymentTestSuite) TestStorageBill_Smoke() { secondarySPBlsPubKeys := make([]bls.PublicKey, 0) blsSignHash := storagetypes.NewSecondarySpSealObjectSignDoc(s.GetChainID(), gvgId, queryHeadObjectResponse.ObjectInfo.Id, storagetypes.GenerateHash(expectChecksum[:])).GetBlsSignHash() // every secondary sp signs the checksums - for i := 1; i < len(s.StorageProviders); i++ { - sig, err := core.BlsSignAndVerify(s.StorageProviders[uint32(i)], blsSignHash) + 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[uint32(i)].BlsKey.PubKey().Bytes()) + pk, err := bls.PublicKeyFromBytes(s.StorageProviders[spID].BlsKey.PubKey().Bytes()) s.Require().NoError(err) secondarySPBlsPubKeys = append(secondarySPBlsPubKeys, pk) } @@ -1079,7 +1080,7 @@ func (s *PaymentTestSuite) TestStorageBill_Smoke() { func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WhenPaymentAccountFrozen() { ctx := context.Background() user := s.GenAndChargeAccounts(1, 1000000)[0] - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() queryParamsRequest := paymenttypes.QueryParamsRequest{} queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) @@ -1094,7 +1095,7 @@ func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WhenPaymentAc s.updateParams(params) // create bucket - bucketName := s.createBucket(user, 0) + bucketName := s.createBucket(sp, user, 0) // create & seal objects _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) @@ -1171,7 +1172,7 @@ func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WithPriceChan ctx := context.Background() // set storage price - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ SpAddr: sp.OperatorKey.GetAddr().String(), Timestamp: 0, @@ -1181,7 +1182,7 @@ func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WithPriceChan user := s.GenAndChargeAccounts(1, 1000000)[0] // create bucket - bucketName := s.createBucket(user, 0) + bucketName := s.createBucket(sp, user, 0) // create & seal objects _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) @@ -1265,7 +1266,7 @@ func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WithPriceChan func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithoutPriceChange() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1284,7 +1285,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithoutPriceChange streamRecordsBefore := s.getStreamRecords(streamAddresses) // create bucket - bucketName := s.createBucket(user, 256) + bucketName := s.createBucket(sp, user, 256) //simulate delete bucket gas msgDeleteBucket := storagetypes.NewMsgDeleteBucket(user.GetAddr(), bucketName) @@ -1352,7 +1353,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithoutPriceChange func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1371,7 +1372,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() streamRecordsBefore := s.getStreamRecords(streamAddresses) // create bucket - bucketName := s.createBucket(user, 256) + bucketName := s.createBucket(sp, user, 256) //simulate delete bucket gas msgDeleteBucket := storagetypes.NewMsgDeleteBucket(user.GetAddr(), bucketName) @@ -1465,7 +1466,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreLessThanReserveTime() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1482,7 +1483,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreLessThanReserve reserveTime := queryParamsResponse.Params.VersionedParams.ReserveTime // create bucket - bucketName := s.createBucket(user, 256) + bucketName := s.createBucket(sp, user, 256) // create & seal objects _, _, objectName1, objectId1, checksums1, payloadSize := s.createObject(user, bucketName, false) @@ -1530,7 +1531,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreLessThanReserve func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreMoreThanReserveTime() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1553,7 +1554,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreMoreThanReserve s.updateParams(params) // create bucket - bucketName := s.createBucket(user, 256) + bucketName := s.createBucket(sp, user, 256) // create & seal objects _, _, objectName1, objectId1, checksums1, payloadSize := s.createObject(user, bucketName, false) @@ -1624,7 +1625,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreMoreThanReserve func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuota() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1647,7 +1648,7 @@ func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuot s.Require().NoError(err) // case: create bucket with zero read quota - bucketName := s.createBucket(user, 0) + bucketName := s.createBucket(sp, user, 0) // bucket created queryHeadBucketRequest := storagetypes.QueryHeadBucketRequest{ @@ -1664,7 +1665,7 @@ func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuot s.Require().Equal(streamRecordsAfter.Tax.NetflowRate, streamRecordsBefore.Tax.NetflowRate) // case: create bucket with none zero read quota - bucketName = s.createBucket(user, 10240) + bucketName = s.createBucket(sp, user, 10240) // bucket created queryHeadBucketRequest = storagetypes.QueryHeadBucketRequest{ @@ -1712,7 +1713,7 @@ func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuot func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithZeroNoneZeroPayload() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1733,7 +1734,7 @@ func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithZeroNoneZeroPayload( s.T().Logf("paymentParams %s, err: %v", paymentParams, err) s.Require().NoError(err) - bucketName := s.createBucket(user, 0) + bucketName := s.createBucket(sp, user, 0) // case: create object with zero payload size streamRecordsBefore := s.getStreamRecords(streamAddresses) @@ -1767,7 +1768,7 @@ func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithZeroNoneZeroPayload( func (s *PaymentTestSuite) TestStorageBill_CancelCreateObject() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1788,7 +1789,7 @@ func (s *PaymentTestSuite) TestStorageBill_CancelCreateObject() { s.T().Logf("paymentParams %s, err: %v", paymentParams, err) s.Require().NoError(err) - bucketName := s.createBucket(user, 0) + bucketName := s.createBucket(sp, user, 0) // create object with none zero payload size streamRecordsBefore := s.getStreamRecords(streamAddresses) @@ -1820,7 +1821,7 @@ func (s *PaymentTestSuite) TestStorageBill_CancelCreateObject() { func (s *PaymentTestSuite) TestStorageBill_SealObject_WithoutPriceChange() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1841,7 +1842,7 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithoutPriceChange() { s.T().Logf("paymentParams %s, err: %v", paymentParams, err) s.Require().NoError(err) - bucketName := s.createBucket(user, 0) + bucketName := s.createBucket(sp, user, 0) // create object with none zero payload size streamRecordsBefore := s.getStreamRecords(streamAddresses) @@ -1874,7 +1875,7 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithoutPriceChange() { func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChange() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1895,7 +1896,7 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChange() { s.T().Logf("paymentParams %s, err: %v", paymentParams, err) s.Require().NoError(err) - bucketName := s.createBucket(user, 102400) + bucketName := s.createBucket(sp, user, 102400) // case: seal object with read price change and storage price change _, _, objectName, objectId, checksums, payloadSize := s.createObject(user, bucketName, false) @@ -1935,7 +1936,7 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChange() { func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1954,12 +1955,12 @@ func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { streamRecordsBefore := s.getStreamRecords(streamAddresses) // full lifecycle - bucketName1 := s.createBucket(user, 0) + bucketName1 := s.createBucket(sp, user, 0) _, _, objectName1, _, _, _ := s.createObject(user, bucketName1, true) _, _, objectName2, objectId2, checksums2, _ := s.createObject(user, bucketName1, false) s.sealObject(bucketName1, objectName2, objectId2, checksums2) - bucketName2 := s.createBucket(user, 1024) + bucketName2 := s.createBucket(sp, user, 1024) _, _, objectName3, objectId3, checksums3, _ := s.createObject(user, bucketName2, false) s.sealObject(bucketName2, objectName3, objectId3, checksums3) _, _, objectName4, objectId4, checksums4, _ := s.createObject(user, bucketName2, false) @@ -1988,7 +1989,7 @@ func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { func (s *PaymentTestSuite) TestVirtualGroup_Settle() { var err error ctx := context.Background() - sp := s.StorageProviders[0] + sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -1998,7 +1999,7 @@ func (s *PaymentTestSuite) TestVirtualGroup_Settle() { family := queryFamilyResponse.GlobalVirtualGroupFamily user := s.GenAndChargeAccounts(1, 1000000)[0] - bucketName := s.createBucket(user, 1024) + bucketName := s.createBucket(sp, user, 1024) _, _, objectName, objectId, checksums, _ := s.createObject(user, bucketName, false) s.sealObject(bucketName, objectName, objectId, checksums) @@ -2052,7 +2053,7 @@ func (s *PaymentTestSuite) TestVirtualGroup_SwapOut() { sp := s.BaseSuite.CreateNewStorageProvider() s.T().Logf("new SP Info: %s", sp.Info.String()) - successorSp := s.StorageProviders[0] + successorSp := s.PickStorageProvider() // create a new gvg group for this storage provider var secondarySPIDs []uint32 @@ -2428,9 +2429,8 @@ func (s *PaymentTestSuite) updateParams(params paymenttypes.Params) { s.T().Logf("new params: %s", params.String()) } -func (s *PaymentTestSuite) createBucketAndObject() (keys.KeyManager, string, string, storagetypes.Uint, [][]byte) { +func (s *PaymentTestSuite) createBucketAndObject(sp *core.StorageProvider) (keys.KeyManager, string, string, storagetypes.Uint, [][]byte) { var err error - sp := s.StorageProviders[0] gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) @@ -2487,9 +2487,8 @@ func (s *PaymentTestSuite) createBucketAndObject() (keys.KeyManager, string, str return user, bucketName, objectName, queryHeadObjectResponse.ObjectInfo.Id, expectChecksum } -func (s *PaymentTestSuite) createBucket(user keys.KeyManager, readQuota uint64) string { +func (s *PaymentTestSuite) createBucket(sp *core.StorageProvider, user keys.KeyManager, readQuota uint64) string { var err error - sp := s.StorageProviders[0] gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) @@ -2514,7 +2513,7 @@ func (s *PaymentTestSuite) createBucket(user keys.KeyManager, readQuota uint64) func (s *PaymentTestSuite) createObject(user keys.KeyManager, bucketName string, empty bool) (keys.KeyManager, string, string, storagetypes.Uint, [][]byte, uint64) { var err error - sp := s.StorageProviders[0] + sp := s.BaseSuite.PickStorageProviderByBucketName(bucketName) // CreateObject objectName := storagetestutils.GenRandomObjectName() @@ -2574,7 +2573,7 @@ func (s *PaymentTestSuite) cancelCreateObject(user keys.KeyManager, bucketName, } func (s *PaymentTestSuite) sealObject(bucketName, objectName string, objectId storagetypes.Uint, checksums [][]byte) *virtualgrouptypes.GlobalVirtualGroup { - sp := s.StorageProviders[0] + sp := s.BaseSuite.PickStorageProviderByBucketName(bucketName) gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) s.T().Log("GVG info: ", gvg.String()) @@ -2586,11 +2585,11 @@ func (s *PaymentTestSuite) sealObject(bucketName, objectName string, objectId st secondarySPBlsPubKeys := make([]bls.PublicKey, 0) blsSignHash := storagetypes.NewSecondarySpSealObjectSignDoc(s.GetChainID(), gvgId, objectId, storagetypes.GenerateHash(checksums[:])).GetBlsSignHash() // every secondary sp signs the checksums - for i := 1; i < len(s.StorageProviders); i++ { - sig, err := core.BlsSignAndVerify(s.StorageProviders[uint32(i)], blsSignHash) + 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[uint32(i)].BlsKey.PubKey().Bytes()) + pk, err := bls.PublicKeyFromBytes(s.StorageProviders[spID].BlsKey.PubKey().Bytes()) s.Require().NoError(err) secondarySPBlsPubKeys = append(secondarySPBlsPubKeys, pk) } diff --git a/x/payment/keeper/storage_fee_charge_test.go b/x/payment/keeper/storage_fee_charge_test.go index 13d2a85b4..2ea181ef2 100644 --- a/x/payment/keeper/storage_fee_charge_test.go +++ b/x/payment/keeper/storage_fee_charge_test.go @@ -25,6 +25,15 @@ func TestApplyFlowChanges(t *testing.T) { *types.NewDefaultStreamRecordChangeWithAddr(user).WithStaticBalanceChange(userInitBalance).WithRateChange(rate.Neg()), *types.NewDefaultStreamRecordChangeWithAddr(sp).WithRateChange(rate), } + sr := &types.StreamRecord{Account: user.String(), + OutFlowCount: 1, + StaticBalance: sdkmath.ZeroInt(), + BufferBalance: sdkmath.ZeroInt(), + LockBalance: sdkmath.ZeroInt(), + NetflowRate: sdkmath.ZeroInt(), + FrozenNetflowRate: sdkmath.ZeroInt(), + } + keeper.SetStreamRecord(ctx, sr) err := keeper.ApplyStreamRecordChanges(ctx, flowChanges) require.NoError(t, err) userStreamRecord, found := keeper.GetStreamRecord(ctx, user) diff --git a/x/storage/keeper/payment_test.go b/x/storage/keeper/payment_test.go index b3b78ca62..1d3d087e1 100644 --- a/x/storage/keeper/payment_test.go +++ b/x/storage/keeper/payment_test.go @@ -194,7 +194,7 @@ func (s *TestSuite) TestGetBucketReadStoreBill() { Id: 1, VirtualPaymentAddress: sample.RandAccAddress().String(), } - s.virtualGroupKeeper.EXPECT().GetGVGFamily(gomock.Any(), gomock.Any(), gomock.Any()). + s.virtualGroupKeeper.EXPECT().GetGVGFamily(gomock.Any(), gomock.Any()). Return(gvgFamily, true).AnyTimes() primarySp := &sptypes.StorageProvider{ From 4d52a126c285cbdf519451ab18073abcb1266139 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Mon, 17 Jul 2023 21:32:26 +0800 Subject: [PATCH 10/33] fix unit test --- x/payment/keeper/storage_fee_charge_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/x/payment/keeper/storage_fee_charge_test.go b/x/payment/keeper/storage_fee_charge_test.go index 2ea181ef2..7c3df2079 100644 --- a/x/payment/keeper/storage_fee_charge_test.go +++ b/x/payment/keeper/storage_fee_charge_test.go @@ -56,6 +56,15 @@ func TestSettleStreamRecord(t *testing.T) { rate := sdkmath.NewInt(-100) staticBalance := sdkmath.NewInt(1e10) change := types.NewDefaultStreamRecordChangeWithAddr(user).WithRateChange(rate).WithStaticBalanceChange(staticBalance) + sr := &types.StreamRecord{Account: user.String(), + OutFlowCount: 1, + StaticBalance: sdkmath.ZeroInt(), + BufferBalance: sdkmath.ZeroInt(), + LockBalance: sdkmath.ZeroInt(), + NetflowRate: sdkmath.ZeroInt(), + FrozenNetflowRate: sdkmath.ZeroInt(), + } + keeper.SetStreamRecord(ctx, sr) _, err := keeper.UpdateStreamRecordByAddr(ctx, change) require.NoError(t, err) // check From 64d9fb08037ccd85b080a070cc9f818260decf3b Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Tue, 18 Jul 2023 09:52:30 +0800 Subject: [PATCH 11/33] handle frozen account --- x/payment/keeper/out_flow.go | 11 ++- x/payment/keeper/storage_fee_charge.go | 103 +++++++++++++++++-------- x/payment/keeper/stream_record.go | 14 +--- x/payment/types/price.go | 7 ++ x/storage/abci.go | 2 + 5 files changed, 92 insertions(+), 45 deletions(-) diff --git a/x/payment/keeper/out_flow.go b/x/payment/keeper/out_flow.go index ab76aec05..0049babfb 100644 --- a/x/payment/keeper/out_flow.go +++ b/x/payment/keeper/out_flow.go @@ -65,10 +65,19 @@ func (k Keeper) DeleteOutFlow(ctx sdk.Context, key []byte) { // MergeActiveOutFlows merge active OutFlows and save them in the store func (k Keeper) MergeActiveOutFlows(ctx sdk.Context, addr sdk.AccAddress, outFlows []types.OutFlow) int { + return k.mergeOutFlows(ctx, addr, types.OUT_FLOW_STATUS_ACTIVE, outFlows) +} + +// MergeFrozenOutFlows merge frozen OutFlows and save them in the store +func (k Keeper) MergeFrozenOutFlows(ctx sdk.Context, addr sdk.AccAddress, outFlows []types.OutFlow) int { + return k.mergeOutFlows(ctx, addr, types.OUT_FLOW_STATUS_FROZEN, outFlows) +} + +func (k Keeper) mergeOutFlows(ctx sdk.Context, addr sdk.AccAddress, status types.OutFlowStatus, outFlows []types.OutFlow) int { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.OutFlowKeyPrefix) deltaCount := 0 for _, outFlow := range outFlows { - outFlow.Status = types.OUT_FLOW_STATUS_ACTIVE + outFlow.Status = status key := types.OutFlowKey(addr, outFlow.Status, sdk.MustAccAddressFromHex(outFlow.ToAddress)) value := store.Get(key) if value == nil { diff --git a/x/payment/keeper/storage_fee_charge.go b/x/payment/keeper/storage_fee_charge.go index 844b49860..c709f7e5c 100644 --- a/x/payment/keeper/storage_fee_charge.go +++ b/x/payment/keeper/storage_fee_charge.go @@ -54,50 +54,85 @@ func (k Keeper) ApplyUserFlowsList(ctx sdk.Context, userFlowsList []types.UserFl currentTime := ctx.BlockTime().Unix() for _, userFlows := range userFlowsList { - var streamRecordChanges []types.StreamRecordChange from := userFlows.From streamRecord, found := k.GetStreamRecord(ctx, from) if !found { streamRecord = types.NewStreamRecord(from, currentTime) } - // calculate rate changes in flowChanges - totalRate := sdk.ZeroInt() - for _, flowChange := range userFlows.Flows { - streamRecordChanges = append(streamRecordChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithRateChange(flowChange.Rate)) - totalRate = totalRate.Add(flowChange.Rate) - } - streamRecordChange := types.NewDefaultStreamRecordChangeWithAddr(from).WithRateChange(totalRate.Neg()) - // storage fee preview - if ctx.IsCheckTx() { - reserveTime := k.GetParams(ctx).VersionedParams.ReserveTime - changeRate := totalRate.Neg() - event := &types.EventFeePreview{ - Account: from.String(), - Amount: changeRate.Mul(sdkmath.NewIntFromUint64(reserveTime)).Abs(), + if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE { + var rateChanges []types.StreamRecordChange + totalRate := sdk.ZeroInt() + for _, flowChange := range userFlows.Flows { + rateChanges = append(rateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithRateChange(flowChange.Rate)) + totalRate = totalRate.Add(flowChange.Rate) } - if changeRate.IsPositive() { - event.FeePreviewType = types.FEE_PREVIEW_TYPE_UNLOCKED_FEE - } else { - event.FeePreviewType = types.FEE_PREVIEW_TYPE_PRELOCKED_FEE + streamRecordChange := types.NewDefaultStreamRecordChangeWithAddr(from).WithRateChange(totalRate.Neg()) + // storage fee preview + if ctx.IsCheckTx() { + reserveTime := k.GetParams(ctx).VersionedParams.ReserveTime + changeRate := totalRate.Neg() + event := &types.EventFeePreview{ + Account: from.String(), + Amount: changeRate.Mul(sdkmath.NewIntFromUint64(reserveTime)).Abs(), + } + if changeRate.IsPositive() { + event.FeePreviewType = types.FEE_PREVIEW_TYPE_UNLOCKED_FEE + } else { + event.FeePreviewType = types.FEE_PREVIEW_TYPE_PRELOCKED_FEE + } + _ = ctx.EventManager().EmitTypedEvents(event) + } + err = k.UpdateStreamRecord(ctx, streamRecord, streamRecordChange) + if err != nil { + return fmt.Errorf("apply stream record changes for user failed: %w", err) } - _ = ctx.EventManager().EmitTypedEvents(event) - } - err = k.UpdateStreamRecord(ctx, streamRecord, streamRecordChange) - if err != nil { - return fmt.Errorf("apply stream record changes for user failed: %w", err) - } - // update flows - deltaFlowCount := k.MergeActiveOutFlows(ctx, from, userFlows.Flows) // deltaFlowCount can be negative - streamRecord.OutFlowCount = uint64(int64(streamRecord.OutFlowCount) + int64(deltaFlowCount)) + // update flows + deltaFlowCount := k.MergeActiveOutFlows(ctx, from, userFlows.Flows) // deltaFlowCount can be negative + streamRecord.OutFlowCount = uint64(int64(streamRecord.OutFlowCount) + int64(deltaFlowCount)) - k.SetStreamRecord(ctx, streamRecord) + k.SetStreamRecord(ctx, streamRecord) + err = k.ApplyStreamRecordChanges(ctx, rateChanges) + if err != nil { + return fmt.Errorf("apply stream record changes failed: %w", err) + } + } else { // frozen status, should be called in end block for stop serving + forced, _ := ctx.Value(types.ForceUpdateStreamRecordKey).(bool) + if !forced { + return fmt.Errorf("stream record %s is frozen", streamRecord.Account) + } - // when the account is frozen, the flows to GVG/GVG family had or will be deducted, - // then should not update the flow rate - // for user's payment account, the frozen flow rate will be updated - if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE { - err = k.ApplyStreamRecordChanges(ctx, streamRecordChanges) + // the stream record could be totally frozen, or in the process of resuming + var activeOutFlows, frozenOutFlows []types.OutFlow + var activeRateChanges, frozenRateChanges []types.StreamRecordChange + totalActiveRate, totalFrozenRate := sdk.ZeroInt(), sdk.ZeroInt() + for _, flowChange := range userFlows.Flows { + outFlow := k.GetOutFlow(ctx, sdk.MustAccAddressFromHex(streamRecord.Account), types.OUT_FLOW_STATUS_FROZEN, sdk.MustAccAddressFromHex(flowChange.ToAddress)) + if outFlow != nil { + frozenOutFlows = append(frozenOutFlows, flowChange) + frozenRateChanges = append(frozenRateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithFrozenRateChange(flowChange.Rate)) + totalFrozenRate = totalFrozenRate.Add(flowChange.Rate) + } else { + activeOutFlows = append(activeOutFlows, flowChange) + activeRateChanges = append(activeRateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithRateChange(flowChange.Rate)) + totalActiveRate = totalActiveRate.Add(flowChange.Rate) + } + } + streamRecordChange := types.NewDefaultStreamRecordChangeWithAddr(from). + WithRateChange(totalActiveRate.Neg()).WithFrozenRateChange(totalFrozenRate.Neg()) + err = k.UpdateFrozenStreamRecord(ctx, streamRecord, streamRecordChange) + if err != nil { + return fmt.Errorf("apply stream record changes for user failed: %w", err) + } + + // update flows + deltaActiveFlowCount := k.MergeActiveOutFlows(ctx, from, activeOutFlows) // can be negative + deltaFrozenFlowCount := k.MergeFrozenOutFlows(ctx, from, frozenOutFlows) // can be negative + streamRecord.OutFlowCount = uint64(int64(streamRecord.OutFlowCount) + int64(deltaActiveFlowCount) + int64(deltaFrozenFlowCount)) + + k.SetStreamRecord(ctx, streamRecord) + //only apply activeRateChanges, for frozen rate changes, the out flow to gvg & gvg family had been deducted when settling + err = k.ApplyStreamRecordChanges(ctx, activeRateChanges) if err != nil { return fmt.Errorf("apply stream record changes failed: %w", err) } diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index 9466a8537..87d49cab1 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -123,23 +123,17 @@ func (k Keeper) UpdateFrozenStreamRecord(ctx sdk.Context, streamRecord *types.St return fmt.Errorf("lock balance can not become negative, current: %s", streamRecord.LockBalance) } } - // update netflow - // when there are object/bucket deletions in end block, the frozen rate should be updated if !change.RateChange.IsZero() { - streamRecord.FrozenNetflowRate = streamRecord.FrozenNetflowRate.Add(change.RateChange) + streamRecord.NetflowRate = streamRecord.NetflowRate.Add(change.RateChange) + } + if !change.FrozenRateChange.IsZero() { + streamRecord.FrozenNetflowRate = streamRecord.FrozenNetflowRate.Add(change.FrozenRateChange) } return nil } func (k Keeper) UpdateStreamRecord(ctx sdk.Context, streamRecord *types.StreamRecord, change *types.StreamRecordChange) error { forced, _ := ctx.Value(types.ForceUpdateStreamRecordKey).(bool) // force update in end block - if streamRecord.Status != types.STREAM_ACCOUNT_STATUS_ACTIVE { - if forced { //stream record is frozen - return k.UpdateFrozenStreamRecord(ctx, streamRecord, change) - } - return fmt.Errorf("stream account %s is frozen", streamRecord.Account) - } - isPay := change.StaticBalanceChange.IsNegative() || change.RateChange.IsNegative() currentTimestamp := ctx.BlockTime().Unix() timestamp := streamRecord.CrudTimestamp diff --git a/x/payment/types/price.go b/x/payment/types/price.go index a1b144ae8..6b67c292b 100644 --- a/x/payment/types/price.go +++ b/x/payment/types/price.go @@ -10,6 +10,7 @@ type StreamRecordChange struct { RateChange sdkmath.Int StaticBalanceChange sdkmath.Int LockBalanceChange sdkmath.Int + FrozenRateChange sdkmath.Int } func NewDefaultStreamRecordChangeWithAddr(addr sdk.AccAddress) *StreamRecordChange { @@ -18,6 +19,7 @@ func NewDefaultStreamRecordChangeWithAddr(addr sdk.AccAddress) *StreamRecordChan RateChange: sdkmath.ZeroInt(), StaticBalanceChange: sdkmath.ZeroInt(), LockBalanceChange: sdkmath.ZeroInt(), + FrozenRateChange: sdkmath.ZeroInt(), } } @@ -36,6 +38,11 @@ func (change *StreamRecordChange) WithLockBalanceChange(lockBalanceChange sdkmat return change } +func (change *StreamRecordChange) WithFrozenRateChange(frozenRateChange sdkmath.Int) *StreamRecordChange { + change.FrozenRateChange = frozenRateChange + return change +} + type StoragePriceParams struct { PrimarySp uint32 PriceTime int64 diff --git a/x/storage/abci.go b/x/storage/abci.go index e42e1b51b..b395f512c 100644 --- a/x/storage/abci.go +++ b/x/storage/abci.go @@ -31,6 +31,7 @@ func EndBlocker(ctx sdk.Context, keeper k.Keeper) { deleted, err := keeper.DeleteDiscontinueObjectsUntil(ctx, blockTime, deletionMax) if err != nil { ctx.Logger().Error("should not happen, fail to delete objects, err " + err.Error()) + panic("should not happen") } if deleted >= deletionMax { @@ -41,6 +42,7 @@ func EndBlocker(ctx sdk.Context, keeper k.Keeper) { _, err = keeper.DeleteDiscontinueBucketsUntil(ctx, blockTime, deletionMax-deleted) if err != nil { ctx.Logger().Error("should not happen, fail to delete buckets, err " + err.Error()) + panic("should not happen") } keeper.PersistDeleteInfo(ctx) From 8eda1241abff45dfe11e2b96307aab469bc25c23 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Tue, 18 Jul 2023 14:39:29 +0800 Subject: [PATCH 12/33] add some payment test cases --- e2e/tests/payment_test.go | 192 +++++++++++++++++++++++- x/payment/keeper/auto_resume_record.go | 2 +- x/payment/keeper/msg_server_withdraw.go | 4 + x/payment/keeper/stream_record.go | 18 ++- x/payment/keeper/stream_record_test.go | 12 +- 5 files changed, 220 insertions(+), 8 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index d828812d6..2179ae3ed 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -49,7 +49,7 @@ func (s *PaymentTestSuite) SetupSuite() { func (s *PaymentTestSuite) SetupTest() {} -func (s *PaymentTestSuite) TestPaymentAccount() { +func (s *PaymentTestSuite) TestCreatePaymentAccount() { user := s.GenAndChargeAccounts(1, 100)[0] ctx := context.Background() // create a new payment account @@ -292,7 +292,95 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteObjectAfterReserveTimeChang s.updateParams(params) } -func (s *PaymentTestSuite) TestDepositAndResume_InOneBlock() { +func (s *PaymentTestSuite) TestDeposit_ActiveAccount() { + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + user := s.GenAndChargeAccounts(1, 1000000)[0] + userAddr := user.GetAddr().String() + var err error + + params, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("params %s, err: %v", params, err) + s.Require().NoError(err) + reserveTime := params.Params.VersionedParams.ReserveTime + queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + }) + s.T().Logf("queryGetSpStoragePriceByTimeResp %s, err: %v", queryGetSpStoragePriceByTimeResp, err) + s.Require().NoError(err) + + bucketChargedReadQuota := uint64(1000) + readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice + totalUserRate := readPrice.MulInt(sdkmath.NewIntFromUint64(bucketChargedReadQuota)).TruncateInt() + taxRateParam := params.Params.VersionedParams.ValidatorTaxRate + taxStreamRate := taxRateParam.MulInt(totalUserRate).TruncateInt() + expectedRate := totalUserRate.Add(taxStreamRate) + paymentAccountBNBNeeded := expectedRate.Mul(sdkmath.NewIntFromUint64(reserveTime)) + s.T().Log("paymentAccountBNBNeeded", paymentAccountBNBNeeded.String()) + + // create payment account and deposit + msgCreatePaymentAccount := &paymenttypes.MsgCreatePaymentAccount{ + Creator: userAddr, + } + _ = s.SendTxBlock(user, msgCreatePaymentAccount) + paymentAccountsReq := &paymenttypes.QueryGetPaymentAccountsByOwnerRequest{Owner: userAddr} + paymentAccounts, err := s.Client.PaymentQueryClient.GetPaymentAccountsByOwner(ctx, paymentAccountsReq) + s.Require().NoError(err) + s.T().Logf("paymentAccounts %s", core.YamlString(paymentAccounts)) + paymentAddr := paymentAccounts.PaymentAccounts[0] + s.Require().Lenf(paymentAccounts.PaymentAccounts, 1, "paymentAccounts %s", core.YamlString(paymentAccounts)) + + // deposit BNB needed + msgDeposit := &paymenttypes.MsgDeposit{ + Creator: user.GetAddr().String(), + To: paymentAddr, + Amount: paymentAccountBNBNeeded.MulRaw(2), // deposit more than needed + } + _ = s.SendTxBlock(user, msgDeposit) + + // create bucket + bucketName := storagetestutils.GenRandomBucketName() + msgCreateBucket := storagetypes.NewMsgCreateBucket( + user.GetAddr(), bucketName, storagetypes.VISIBILITY_TYPE_PUBLIC_READ, sp.OperatorKey.GetAddr(), + sdk.MustAccAddressFromHex(paymentAddr), math.MaxUint, nil, bucketChargedReadQuota) + msgCreateBucket.PrimarySpApproval.GlobalVirtualGroupFamilyId = gvg.FamilyId + msgCreateBucket.PrimarySpApproval.Sig, err = sp.ApprovalKey.Sign(msgCreateBucket.GetApprovalBytes()) + s.Require().NoError(err) + s.SendTxBlock(user, msgCreateBucket) + + // check payment account stream record + paymentAccountStreamRecord := s.getStreamRecord(paymentAddr) + s.T().Logf("paymentAccountStreamRecord %s", core.YamlString(paymentAccountStreamRecord)) + s.Require().Equal(expectedRate.String(), paymentAccountStreamRecord.NetflowRate.Neg().String()) + s.Require().Equal(paymentAccountStreamRecord.BufferBalance.String(), paymentAccountBNBNeeded.String()) + s.Require().Equal(paymentAccountStreamRecord.StaticBalance.String(), paymentAccountBNBNeeded.String()) + + time.Sleep(5 * time.Second) + + // deposit + msgDeposit = &paymenttypes.MsgDeposit{ + Creator: userAddr, + To: paymentAddr, + Amount: paymentAccountBNBNeeded, + } + _ = s.SendTxBlock(user, msgDeposit) + + // check payment account stream record + paymentAccountStreamRecordAfter := s.getStreamRecord(paymentAddr) + s.T().Logf("paymentAccountStreamRecordAfter %s", core.YamlString(paymentAccountStreamRecordAfter)) + s.Require().Equal(paymentAccountStreamRecordAfter.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) + + settledTime := paymentAccountStreamRecordAfter.CrudTimestamp - paymentAccountStreamRecord.CrudTimestamp + settledBalance := expectedRate.MulRaw(settledTime) + paymentBalanceChange := paymentAccountStreamRecordAfter.StaticBalance.Sub(paymentAccountStreamRecord.StaticBalance). + Add(paymentAccountStreamRecordAfter.BufferBalance.Sub(paymentAccountStreamRecord.BufferBalance)) + s.Require().Equal(settledBalance.Add(paymentBalanceChange).Int64(), paymentAccountBNBNeeded.Int64()) + s.Require().Equal(paymentAccountBNBNeeded.MulRaw(3), settledBalance.Add(paymentAccountStreamRecordAfter.StaticBalance.Add(paymentAccountStreamRecordAfter.BufferBalance))) +} + +func (s *PaymentTestSuite) TestDeposit_ResumeInOneBlock() { ctx := context.Background() sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() @@ -406,7 +494,7 @@ func (s *PaymentTestSuite) TestDepositAndResume_InOneBlock() { s.Require().Equal(paymentAccountStreamRecordAfterDeposit2.StaticBalance.Add(paymentAccountStreamRecordAfterDeposit2.BufferBalance).String(), paymentAccountStreamRecordAfterDeposit1.StaticBalance.Add(depositAmount2).String()) } -func (s *PaymentTestSuite) TestDepositAndResume_InBlocks() { +func (s *PaymentTestSuite) TestDeposit_ResumeInBlocks() { ctx := context.Background() // update params queryParamsRequest := paymenttypes.QueryParamsRequest{} @@ -528,6 +616,16 @@ func (s *PaymentTestSuite) TestDepositAndResume_InBlocks() { paymentAccountStreamRecordAfterDeposit = s.getStreamRecord(paymentAddr) s.T().Logf("paymentAccountStreamRecordAfterDeposit %s at %d", core.YamlString(paymentAccountStreamRecordAfterDeposit), latestBlock.Block.Height) + if paymentAccountStreamRecordAfterDeposit.Status == paymenttypes.STREAM_ACCOUNT_STATUS_FROZEN && + !paymentAccountStreamRecordAfterDeposit.NetflowRate.IsZero() { + s.T().Log("trying to deposit, which will error") + msgDeposit = &paymenttypes.MsgDeposit{ + Creator: user.GetAddr().String(), + To: paymentAddr, + Amount: paymentAccountBNBNeeded, + } + s.SendTxBlockWithExpectErrorString(msgDeposit, user, "resuming") + } if paymentAccountStreamRecordAfterDeposit.Status == paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE { break } @@ -819,6 +917,94 @@ func (s *PaymentTestSuite) TestAutoSettle_InBlocks() { s.updateParams(params) } +func (s *PaymentTestSuite) TestWithdraw() { + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + user := s.GenAndChargeAccounts(1, 1000000)[0] + userAddr := user.GetAddr().String() + var err error + + params, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("params %s, err: %v", params, err) + s.Require().NoError(err) + reserveTime := params.Params.VersionedParams.ReserveTime + queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + }) + s.T().Logf("queryGetSpStoragePriceByTimeResp %s, err: %v", queryGetSpStoragePriceByTimeResp, err) + s.Require().NoError(err) + + bucketChargedReadQuota := uint64(1000) + readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice + totalUserRate := readPrice.MulInt(sdkmath.NewIntFromUint64(bucketChargedReadQuota)).TruncateInt() + taxRateParam := params.Params.VersionedParams.ValidatorTaxRate + taxStreamRate := taxRateParam.MulInt(totalUserRate).TruncateInt() + expectedRate := totalUserRate.Add(taxStreamRate) + paymentAccountBNBNeeded := expectedRate.Mul(sdkmath.NewIntFromUint64(reserveTime)) + s.T().Log("paymentAccountBNBNeeded", paymentAccountBNBNeeded.String()) + + // create payment account and deposit + msgCreatePaymentAccount := &paymenttypes.MsgCreatePaymentAccount{ + Creator: userAddr, + } + _ = s.SendTxBlock(user, msgCreatePaymentAccount) + paymentAccountsReq := &paymenttypes.QueryGetPaymentAccountsByOwnerRequest{Owner: userAddr} + paymentAccounts, err := s.Client.PaymentQueryClient.GetPaymentAccountsByOwner(ctx, paymentAccountsReq) + s.Require().NoError(err) + s.T().Logf("paymentAccounts %s", core.YamlString(paymentAccounts)) + paymentAddr := paymentAccounts.PaymentAccounts[0] + s.Require().Lenf(paymentAccounts.PaymentAccounts, 1, "paymentAccounts %s", core.YamlString(paymentAccounts)) + + // deposit BNB needed + msgDeposit := &paymenttypes.MsgDeposit{ + Creator: user.GetAddr().String(), + To: paymentAddr, + Amount: paymentAccountBNBNeeded.MulRaw(2), // deposit more than needed + } + _ = s.SendTxBlock(user, msgDeposit) + + // create bucket + bucketName := storagetestutils.GenRandomBucketName() + msgCreateBucket := storagetypes.NewMsgCreateBucket( + user.GetAddr(), bucketName, storagetypes.VISIBILITY_TYPE_PUBLIC_READ, sp.OperatorKey.GetAddr(), + sdk.MustAccAddressFromHex(paymentAddr), math.MaxUint, nil, bucketChargedReadQuota) + msgCreateBucket.PrimarySpApproval.GlobalVirtualGroupFamilyId = gvg.FamilyId + msgCreateBucket.PrimarySpApproval.Sig, err = sp.ApprovalKey.Sign(msgCreateBucket.GetApprovalBytes()) + s.Require().NoError(err) + s.SendTxBlock(user, msgCreateBucket) + + // check payment account stream record + paymentAccountStreamRecord := s.getStreamRecord(paymentAddr) + s.T().Logf("paymentAccountStreamRecord %s", core.YamlString(paymentAccountStreamRecord)) + s.Require().Equal(expectedRate.String(), paymentAccountStreamRecord.NetflowRate.Neg().String()) + s.Require().Equal(paymentAccountStreamRecord.BufferBalance.String(), paymentAccountBNBNeeded.String()) + s.Require().Equal(paymentAccountStreamRecord.StaticBalance.String(), paymentAccountBNBNeeded.String()) + + time.Sleep(5 * time.Second) + + dynamicBalanceResp, err := s.Client.DynamicBalance(ctx, &paymenttypes.QueryDynamicBalanceRequest{Account: user.GetAddr().String()}) + s.Require().NoError(err) + s.Require().True(dynamicBalanceResp.DynamicBalance.LT(paymentAccountBNBNeeded)) + + // withdraw more than static balance + withdrawMsg := paymenttypes.NewMsgWithdraw(userAddr, paymentAddr, paymentAccountBNBNeeded) + s.SendTxBlockWithExpectErrorString(withdrawMsg, user, "not enough") + + // withdraw less than static balance + amount := sdk.NewInt(1000) + withdrawMsg = paymenttypes.NewMsgWithdraw(userAddr, paymentAddr, amount) + s.SendTxBlock(user, withdrawMsg) + paymentAccountStreamRecordAfter := s.getStreamRecord(paymentAddr) + s.T().Logf("paymentAccountStreamRecordAfter %s", core.YamlString(paymentAccountStreamRecordAfter)) + + staticBalanceChange := paymentAccountStreamRecord.NetflowRate.MulRaw(paymentAccountStreamRecordAfter.CrudTimestamp - paymentAccountStreamRecord.CrudTimestamp).Neg() + s.Require().Equal(paymentAccountStreamRecord.StaticBalance.Sub(paymentAccountStreamRecordAfter.StaticBalance).Int64(), amount.Add(staticBalanceChange).Int64()) +} + +func (s *PaymentTestSuite) TestWithdraw_WithoutEnoughBalance() {} + func (s *PaymentTestSuite) TestStorageBill_DeleteBucket_WithReadQuota() { var err error ctx := context.Background() diff --git a/x/payment/keeper/auto_resume_record.go b/x/payment/keeper/auto_resume_record.go index 2654e529e..961013e58 100644 --- a/x/payment/keeper/auto_resume_record.go +++ b/x/payment/keeper/auto_resume_record.go @@ -66,7 +66,7 @@ func (k Keeper) ExistsAutoResumeRecord( exists := false for ; iterator.Valid(); iterator.Next() { record := types.ParseAutoResumeRecordKey(iterator.Key()) - if record.Timestamp > timestamp { + if timestamp > 0 && record.Timestamp > timestamp { break } if sdk.MustAccAddressFromHex(record.Addr).Equals(addr) { diff --git a/x/payment/keeper/msg_server_withdraw.go b/x/payment/keeper/msg_server_withdraw.go index 8d8cec396..cf2ff42f8 100644 --- a/x/payment/keeper/msg_server_withdraw.go +++ b/x/payment/keeper/msg_server_withdraw.go @@ -17,6 +17,10 @@ func (k msgServer) Withdraw(goCtx context.Context, msg *types.MsgWithdraw) (*typ if !found { return nil, types.ErrStreamRecordNotFound } + // check status + if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN { + return nil, errors.Wrapf(types.ErrInvalidStreamAccountStatus, "stream record is frozen") + } // check whether creator can withdraw if msg.Creator != msg.From { paymentAccount, found := k.Keeper.GetPaymentAccount(ctx, from) diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index 87d49cab1..794936c5b 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -1,6 +1,7 @@ package keeper import ( + "encoding/json" "fmt" "github.com/cosmos/cosmos-sdk/telemetry" @@ -139,13 +140,19 @@ func (k Keeper) UpdateStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe timestamp := streamRecord.CrudTimestamp params := k.GetParams(ctx) // update delta balance + j, _ := json.Marshal(streamRecord) + fmt.Println("sr_before", string(j)) + if currentTimestamp != timestamp { if !streamRecord.NetflowRate.IsZero() { flowDelta := streamRecord.NetflowRate.MulRaw(currentTimestamp - timestamp) + fmt.Println("flowDelta", flowDelta.String()) streamRecord.StaticBalance = streamRecord.StaticBalance.Add(flowDelta) } streamRecord.CrudTimestamp = currentTimestamp } + j, _ = json.Marshal(streamRecord) + fmt.Println("sr_after", string(j)) // update lock balance if !change.LockBalanceChange.IsZero() { streamRecord.LockBalance = streamRecord.LockBalance.Add(change.LockBalanceChange) @@ -208,13 +215,19 @@ func (k Keeper) SettleStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe crudTimestamp := streamRecord.CrudTimestamp params := k.GetParams(ctx) + j, _ := json.Marshal(streamRecord) + fmt.Println("sr_before", j) + if currentTimestamp != crudTimestamp { if !streamRecord.NetflowRate.IsZero() { flowDelta := streamRecord.NetflowRate.MulRaw(currentTimestamp - crudTimestamp) + fmt.Println("flowDelta", flowDelta.String()) streamRecord.StaticBalance = streamRecord.StaticBalance.Add(flowDelta) } streamRecord.CrudTimestamp = currentTimestamp } + j, _ = json.Marshal(streamRecord) + fmt.Println("sr_after", j) if streamRecord.StaticBalance.IsNegative() { account := sdk.MustAccAddressFromHex(streamRecord.Account) @@ -391,8 +404,9 @@ func (k Keeper) TryResumeStreamRecord(ctx sdk.Context, streamRecord *types.Strea return fmt.Errorf("stream account %s status is not frozen", streamRecord.Account) } - if !streamRecord.NetflowRate.IsZero() { // the account is resuming or settling - return fmt.Errorf("stream account %s status is resuming or settling, please wait", streamRecord.Account) + exists := k.ExistsAutoResumeRecord(ctx, 0, sdk.MustAccAddressFromHex(streamRecord.Account)) + if exists { // the account is resuming or settling + return fmt.Errorf("stream account %s status is resuming, please wait", streamRecord.Account) } params := k.GetParams(ctx) diff --git a/x/payment/keeper/stream_record_test.go b/x/payment/keeper/stream_record_test.go index a0f3a6030..bedbc6f3b 100644 --- a/x/payment/keeper/stream_record_test.go +++ b/x/payment/keeper/stream_record_test.go @@ -18,14 +18,22 @@ func TestTryResumeStreamRecord_InResumingOrSettling(t *testing.T) { keeper, ctx, _ := makePaymentKeeper(t) ctx = ctx.WithBlockTime(time.Now()) - // further deposit to a resuming account is not allowed + account := sample.RandAccAddress() + // deposit to a resuming account is not allowed streamRecord := &types.StreamRecord{ + Account: account.String(), Status: types.STREAM_ACCOUNT_STATUS_FROZEN, NetflowRate: sdkmath.NewInt(-100), } + + keeper.SetAutoResumeRecord(ctx, &types.AutoResumeRecord{ + Timestamp: ctx.BlockTime().Unix() + 10, + Addr: account.String(), + }) + deposit := sdkmath.NewInt(100) err := keeper.TryResumeStreamRecord(ctx, streamRecord, deposit) - require.ErrorContains(t, err, "resuming") + require.ErrorContains(t, err, "is resuming") } func TestTryResumeStreamRecord_ResumeInOneBlock(t *testing.T) { From 90932ef3ba682d20de0d3463c5123fee5210eb2b Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Tue, 18 Jul 2023 14:41:36 +0800 Subject: [PATCH 13/33] fix lint issue --- x/payment/keeper/storage_fee_charge.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/x/payment/keeper/storage_fee_charge.go b/x/payment/keeper/storage_fee_charge.go index c709f7e5c..0b97706c1 100644 --- a/x/payment/keeper/storage_fee_charge.go +++ b/x/payment/keeper/storage_fee_charge.go @@ -104,13 +104,14 @@ func (k Keeper) ApplyUserFlowsList(ctx sdk.Context, userFlowsList []types.UserFl // the stream record could be totally frozen, or in the process of resuming var activeOutFlows, frozenOutFlows []types.OutFlow - var activeRateChanges, frozenRateChanges []types.StreamRecordChange + var activeRateChanges []types.StreamRecordChange + //var frozenRateChanges []types.StreamRecordChange totalActiveRate, totalFrozenRate := sdk.ZeroInt(), sdk.ZeroInt() for _, flowChange := range userFlows.Flows { outFlow := k.GetOutFlow(ctx, sdk.MustAccAddressFromHex(streamRecord.Account), types.OUT_FLOW_STATUS_FROZEN, sdk.MustAccAddressFromHex(flowChange.ToAddress)) if outFlow != nil { frozenOutFlows = append(frozenOutFlows, flowChange) - frozenRateChanges = append(frozenRateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithFrozenRateChange(flowChange.Rate)) + //frozenRateChanges = append(frozenRateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithFrozenRateChange(flowChange.Rate)) totalFrozenRate = totalFrozenRate.Add(flowChange.Rate) } else { activeOutFlows = append(activeOutFlows, flowChange) From 471b5d5f9bc75339fdd302a765c82b1db1c1efba Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Wed, 19 Jul 2023 10:12:48 +0800 Subject: [PATCH 14/33] remove some debug logs --- x/payment/keeper/stream_record.go | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index 794936c5b..692371359 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -1,7 +1,6 @@ package keeper import ( - "encoding/json" "fmt" "github.com/cosmos/cosmos-sdk/telemetry" @@ -140,9 +139,6 @@ func (k Keeper) UpdateStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe timestamp := streamRecord.CrudTimestamp params := k.GetParams(ctx) // update delta balance - j, _ := json.Marshal(streamRecord) - fmt.Println("sr_before", string(j)) - if currentTimestamp != timestamp { if !streamRecord.NetflowRate.IsZero() { flowDelta := streamRecord.NetflowRate.MulRaw(currentTimestamp - timestamp) @@ -151,8 +147,7 @@ func (k Keeper) UpdateStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe } streamRecord.CrudTimestamp = currentTimestamp } - j, _ = json.Marshal(streamRecord) - fmt.Println("sr_after", string(j)) + // update lock balance if !change.LockBalanceChange.IsZero() { streamRecord.LockBalance = streamRecord.LockBalance.Add(change.LockBalanceChange) @@ -215,9 +210,6 @@ func (k Keeper) SettleStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe crudTimestamp := streamRecord.CrudTimestamp params := k.GetParams(ctx) - j, _ := json.Marshal(streamRecord) - fmt.Println("sr_before", j) - if currentTimestamp != crudTimestamp { if !streamRecord.NetflowRate.IsZero() { flowDelta := streamRecord.NetflowRate.MulRaw(currentTimestamp - crudTimestamp) @@ -226,8 +218,6 @@ func (k Keeper) SettleStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe } streamRecord.CrudTimestamp = currentTimestamp } - j, _ = json.Marshal(streamRecord) - fmt.Println("sr_after", j) if streamRecord.StaticBalance.IsNegative() { account := sdk.MustAccAddressFromHex(streamRecord.Account) @@ -545,6 +535,7 @@ func (k Keeper) AutoResume(ctx sdk.Context) { if !flowIterator.Valid() || finished { if !streamRecord.FrozenNetflowRate.IsZero() { ctx.Logger().Error("should not happen, stream frozen netflow rate is not zero", "address", streamRecord.Account) + panic("should not happen") } streamRecord.Status = types.STREAM_ACCOUNT_STATUS_ACTIVE change := types.NewDefaultStreamRecordChangeWithAddr(addr) From 5828b26c5feb843513d4cad1f56423cd74b22634 Mon Sep 17 00:00:00 2001 From: mocky-b Date: Wed, 19 Jul 2023 14:30:56 +0800 Subject: [PATCH 15/33] 1. add copy object testcase 2. add update bucket quota and payment testcase --- e2e/core/basesuite.go | 6 +- e2e/tests/storage_bill_test.go | 562 +++++++++++++++++++++++++++++++++ 2 files changed, 567 insertions(+), 1 deletion(-) create mode 100644 e2e/tests/storage_bill_test.go diff --git a/e2e/core/basesuite.go b/e2e/core/basesuite.go index 24f503c21..0cb59b14a 100644 --- a/e2e/core/basesuite.go +++ b/e2e/core/basesuite.go @@ -195,7 +195,7 @@ func (s *BaseSuite) SendTxBlockWithExpectErrorString(msg sdk.Msg, from keys.KeyM } s.Client.SetKeyManager(from) _, err := s.Client.BroadcastTx(context.Background(), []sdk.Msg{msg}, txOpt) - s.T().Logf("tx failed, err: %s, expect error string: %s", err, expectErrorString) + s.T().Logf("tx failed, err: %v, expect error string: %s", err, expectErrorString) s.Require().Error(err) s.Require().True(strings.Contains(err.Error(), expectErrorString)) } @@ -353,6 +353,10 @@ func (sp *StorageProvider) GetFirstGlobalVirtualGroup() (*virtualgroupmoduletype } return nil, false } +func (sp *StorageProvider) UpdateSPPrice() (*virtualgroupmoduletypes.GlobalVirtualGroup, bool) { + + return nil, false +} func (s *BaseSuite) NewSpAcc() *StorageProvider { userAccs := s.GenAndChargeAccounts(5, 1000000) diff --git a/e2e/tests/storage_bill_test.go b/e2e/tests/storage_bill_test.go new file mode 100644 index 000000000..0c743b21c --- /dev/null +++ b/e2e/tests/storage_bill_test.go @@ -0,0 +1,562 @@ +package tests + +import ( + "context" + "math" + "sort" + "time" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/bnb-chain/greenfield/e2e/core" + "github.com/bnb-chain/greenfield/sdk/keys" + "github.com/bnb-chain/greenfield/sdk/types" + storagetestutils "github.com/bnb-chain/greenfield/testutil/storage" + paymenttypes "github.com/bnb-chain/greenfield/x/payment/types" + sptypes "github.com/bnb-chain/greenfield/x/sp/types" + storagetypes "github.com/bnb-chain/greenfield/x/storage/types" + virtualgrouptypes "github.com/bnb-chain/greenfield/x/virtualgroup/types" +) + +func (s *PaymentTestSuite) copyObject(user keys.KeyManager, sp *core.StorageProvider, bucketName, objectName, dstBucketName, dstObjectName string) (*storagetypes.ObjectInfo, error) { + msgCopyObject := storagetypes.NewMsgCopyObject(user.GetAddr(), bucketName, dstBucketName, objectName, dstObjectName, math.MaxUint, nil) + msgCopyObject.DstPrimarySpApproval.Sig, _ = sp.ApprovalKey.Sign(msgCopyObject.GetApprovalBytes()) + + s.SendTxBlock(user, msgCopyObject) + // HeadObject + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: dstBucketName, + ObjectName: dstObjectName, + } + headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) + return headObjectResponse.ObjectInfo, err + +} + +func (s *PaymentTestSuite) updateBucket(user keys.KeyManager, bucketName string, paymentAddress string, chargedReadQuota uint64) (*storagetypes.BucketInfo, error) { + + msgUpdateBucketInfo := storagetypes.NewMsgUpdateBucketInfo( + user.GetAddr(), bucketName, &chargedReadQuota, user.GetAddr(), storagetypes.VISIBILITY_TYPE_PRIVATE) + if paymentAddress != "" { + msgUpdateBucketInfo.PaymentAddress = paymentAddress + } + s.SendTxBlock(user, msgUpdateBucketInfo) + + queryHeadObjectRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + headObjectResponse, err := s.Client.HeadBucket(context.Background(), &queryHeadObjectRequest) + return headObjectResponse.BucketInfo, err + +} + +// TestStorageBill_CopyObject_WithoutPriceChange +func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithoutPriceChange() { + var err error + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user0 := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user0.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + bucketName := s.createBucket(sp, user0, 0) + + // create object with none zero payload size + streamRecordsBefore := s.getStreamRecords(streamAddresses) + _, _, objectName, objectId, checksums, payloadSize := s.createObject(user0, bucketName, false) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + lockFee := s.calculateLockFee(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.LockBalance.Sub(streamRecordsBefore.User.LockBalance), lockFee) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // case: seal object without price change + s.sealObject(bucketName, objectName, objectId, checksums) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) + gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + + //distBucketName := s.createBucket(sp, user0, 0) + distBucketName := bucketName + distObjectName := storagetestutils.GenRandomObjectName() + + objectIfo, err := s.copyObject(user0, sp, bucketName, objectName, distBucketName, distObjectName) + s.Require().NoError(err) + s.sealObject(distBucketName, distObjectName, objectIfo.Id, objectIfo.Checksums) + // assertions + streamRecordsAfterCopy := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfterCopy.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfterCopy.User.LockBalance, sdkmath.ZeroInt()) + //gvgFamilyRate1, gvgRate1, taxRate1, userTotalRate1 := s.calculateStorageRates(sp,distBucketName, distObjectName, payloadSize) + s.Require().Equal(streamRecordsAfterCopy.User.NetflowRate.Sub(streamRecordsAfter.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfterCopy.GVGFamily.NetflowRate.Sub(streamRecordsAfter.GVGFamily.NetflowRate), gvgFamilyRate) + s.Require().Equal(streamRecordsAfterCopy.GVG.NetflowRate.Sub(streamRecordsAfter.GVG.NetflowRate), gvgRate) + s.Require().Equal(streamRecordsAfterCopy.Tax.NetflowRate.Sub(streamRecordsAfter.Tax.NetflowRate), taxRate) +} + +// TestStorageBill_CopyObject_WithoutPriceChange +func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithPriceChange() { + var err error + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user0 := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user0.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + bucketName := s.createBucket(sp, user0, 0) + + // create object with none zero payload size + streamRecordsBefore := s.getStreamRecords(streamAddresses) + _, _, objectName, objectId, checksums, payloadSize := s.createObject(user0, bucketName, false) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + lockFee := s.calculateLockFee(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.LockBalance.Sub(streamRecordsBefore.User.LockBalance), lockFee) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // case: seal object without price change + s.sealObject(bucketName, objectName, objectId, checksums) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) + gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: 0, + }) + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(1000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + distBucketName := s.createBucket(sp, user0, 0) + distObjectName := storagetestutils.GenRandomObjectName() + objectIfo, err := s.copyObject(user0, sp, bucketName, objectName, distBucketName, distObjectName) + s.Require().NoError(err) + s.sealObject(distBucketName, distObjectName, objectIfo.Id, objectIfo.Checksums) + // assertions + streamRecordsAfterCopy := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfterCopy.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfterCopy.User.LockBalance, sdkmath.ZeroInt()) + gvgFamilyRate1, gvgRate1, taxRate1, userTotalRate1 := s.calculateStorageRates(sp, distBucketName, distObjectName, payloadSize) + s.Require().Equal(streamRecordsAfterCopy.GVGFamily.NetflowRate.Sub(streamRecordsAfter.GVGFamily.NetflowRate), gvgFamilyRate1) + s.Require().Equal(streamRecordsAfterCopy.GVG.NetflowRate.Sub(streamRecordsAfter.GVG.NetflowRate), gvgRate1) + s.Require().Equal(streamRecordsAfterCopy.Tax.NetflowRate.Sub(streamRecordsAfter.Tax.NetflowRate), taxRate1) + s.Require().Equal(streamRecordsAfterCopy.User.NetflowRate.Sub(streamRecordsAfter.User.NetflowRate).BigInt().String(), userTotalRate1.Neg().BigInt().String()) + +} + +// TestStorageBill_UpdateBucketQuota +func (s *PaymentTestSuite) TestStorageBill_UpdateBucketQuota() { + var err error + ctx := context.Background() + sp := s.PickStorageProvider() + // recover price + defer s.RecoverSPPrice(sp) + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 10)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + // case: create bucket with zero read quota + bucketName := s.createBucket(sp, user, 0) + + // bucket created + queryHeadBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + _, err = s.Client.HeadBucket(ctx, &queryHeadBucketRequest) + s.Require().NoError(err) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate, streamRecordsBefore.User.NetflowRate) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate, streamRecordsBefore.GVGFamily.NetflowRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate, streamRecordsBefore.Tax.NetflowRate) + + readQuota := uint64(1024 * 1024 * 100) + // case: update bucket read quota + bucketInfo, err := s.updateBucket(user, bucketName, "", readQuota) + s.Require().NoError(err) + + // check price and rate calculation + queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: time.Now().Unix(), + }) + s.T().Logf("queryGetSpStoragePriceByTimeResp %s, err: %v", queryGetSpStoragePriceByTimeResp, err) + s.Require().NoError(err) + + readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice + readChargeRate := readPrice.MulInt(sdk.NewIntFromUint64(bucketInfo.ChargedReadQuota)).TruncateInt() + s.T().Logf("readPrice: %s, readChargeRate: %s", readPrice, readChargeRate) + taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() + userTotalRate := readChargeRate.Add(taxRate) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), readChargeRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + + expectedOutFlows := []paymenttypes.OutFlow{ + {ToAddress: family.VirtualPaymentAddress, Rate: readChargeRate}, + {ToAddress: paymenttypes.ValidatorTaxPoolAddress.String(), Rate: taxRate}, + } + userOutFlowsResponse, err := s.Client.OutFlows(ctx, &paymenttypes.QueryOutFlowsRequest{Account: user.GetAddr().String()}) + s.Require().NoError(err) + sort.Slice(userOutFlowsResponse.OutFlows, func(i, j int) bool { + return userOutFlowsResponse.OutFlows[i].ToAddress < userOutFlowsResponse.OutFlows[j].ToAddress + }) + sort.Slice(expectedOutFlows, func(i, j int) bool { + return expectedOutFlows[i].ToAddress < expectedOutFlows[j].ToAddress + }) + s.Require().Equal(expectedOutFlows, userOutFlowsResponse.OutFlows) + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice.MulInt64(100), + FreeReadQuota: queryGetSpStoragePriceByTimeResp.SpStoragePrice.FreeReadQuota, + StorePrice: queryGetSpStoragePriceByTimeResp.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + // case: update bucket read quota + bucketInfo, err = s.updateBucket(user, bucketName, "", readQuota*2) + s.Require().NoError(err) + + // check price and rate calculation + queryGetSpStoragePriceByTimeResp, err = s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: time.Now().Unix(), + }) + s.T().Logf("queryGetSpStoragePriceByTimeResp %s, err: %v", queryGetSpStoragePriceByTimeResp, err) + s.Require().NoError(err) + + readPrice = queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice + readChargeRate = readPrice.MulInt(sdk.NewIntFromUint64(bucketInfo.ChargedReadQuota)).TruncateInt() + s.T().Logf("readPrice: %s, readChargeRate: %s", readPrice, readChargeRate) + taxRate = paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() + userTotalRate = readChargeRate.Add(taxRate) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), readChargeRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + + expectedOutFlows = []paymenttypes.OutFlow{ + {ToAddress: family.VirtualPaymentAddress, Rate: readChargeRate}, + {ToAddress: paymenttypes.ValidatorTaxPoolAddress.String(), Rate: taxRate}, + } + userOutFlowsResponse, err = s.Client.OutFlows(ctx, &paymenttypes.QueryOutFlowsRequest{Account: user.GetAddr().String()}) + s.Require().NoError(err) + sort.Slice(userOutFlowsResponse.OutFlows, func(i, j int) bool { + return userOutFlowsResponse.OutFlows[i].ToAddress < userOutFlowsResponse.OutFlows[j].ToAddress + }) + sort.Slice(expectedOutFlows, func(i, j int) bool { + return expectedOutFlows[i].ToAddress < expectedOutFlows[j].ToAddress + }) + s.Require().Equal(expectedOutFlows, userOutFlowsResponse.OutFlows) + // set big read price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice.MulInt64(1024 * 1024 * 1024), + FreeReadQuota: queryGetSpStoragePriceByTimeResp.SpStoragePrice.FreeReadQuota, + StorePrice: queryGetSpStoragePriceByTimeResp.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + chargedReadQuota := readQuota * 1024 * 1024 + msgUpdateBucketInfo := storagetypes.NewMsgUpdateBucketInfo( + user.GetAddr(), bucketName, &chargedReadQuota, user.GetAddr(), storagetypes.VISIBILITY_TYPE_PRIVATE) + + s.SendTxBlockWithExpectErrorString(msgUpdateBucketInfo, user, "apply user flows list failed") + +} + +// TestStorageBill_UpdatePaymentAddress +func (s *PaymentTestSuite) TestStorageBill_UpdatePaymentAddress() { + var err error + ctx := context.Background() + sp := s.PickStorageProvider() + defer s.RecoverSPPrice(sp) + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 100)[0] + + paymentAccountAddr := s.CreatePaymentAccount(user, 1, 17) + paymentAcc, err := sdk.AccAddressFromHexUnsafe(paymentAccountAddr) + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + // case: create bucket with zero read quota + bucketName := s.createBucket(sp, user, 0) + + // bucket created + queryHeadBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + _, err = s.Client.HeadBucket(ctx, &queryHeadBucketRequest) + s.Require().NoError(err) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate, streamRecordsBefore.User.NetflowRate) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate, streamRecordsBefore.GVGFamily.NetflowRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate, streamRecordsBefore.Tax.NetflowRate) + + readQuota := uint64(1024 * 100) + // case: update bucket read quota + bucketInfo, err := s.updateBucket(user, bucketName, "", readQuota) + s.Require().NoError(err) + + // check price and rate calculation + queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: time.Now().Unix(), + }) + s.T().Logf("queryGetSpStoragePriceByTimeResp %s, err: %v", queryGetSpStoragePriceByTimeResp, err) + s.Require().NoError(err) + + readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice + readChargeRate := readPrice.MulInt(sdk.NewIntFromUint64(bucketInfo.ChargedReadQuota)).TruncateInt() + s.T().Logf("readPrice: %s, readChargeRate: %s", readPrice, readChargeRate) + taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() + userTotalRate := readChargeRate.Add(taxRate) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), readChargeRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + + expectedOutFlows := []paymenttypes.OutFlow{ + {ToAddress: family.VirtualPaymentAddress, Rate: readChargeRate}, + {ToAddress: paymenttypes.ValidatorTaxPoolAddress.String(), Rate: taxRate}, + } + userOutFlowsResponse, err := s.Client.OutFlows(ctx, &paymenttypes.QueryOutFlowsRequest{Account: user.GetAddr().String()}) + s.Require().NoError(err) + sort.Slice(userOutFlowsResponse.OutFlows, func(i, j int) bool { + return userOutFlowsResponse.OutFlows[i].ToAddress < userOutFlowsResponse.OutFlows[j].ToAddress + }) + sort.Slice(expectedOutFlows, func(i, j int) bool { + return expectedOutFlows[i].ToAddress < expectedOutFlows[j].ToAddress + }) + s.Require().Equal(expectedOutFlows, userOutFlowsResponse.OutFlows) + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice.MulInt64(100), + FreeReadQuota: queryGetSpStoragePriceByTimeResp.SpStoragePrice.FreeReadQuota, + StorePrice: queryGetSpStoragePriceByTimeResp.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + // case: update bucket paymentAccountAddr + bucketInfo, err = s.updateBucket(user, bucketName, paymentAccountAddr, readQuota) + s.Require().NoError(err) + + // check price and rate calculation + queryGetSpStoragePriceByTimeResp, err = s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: time.Now().Unix(), + }) + s.T().Logf("queryGetSpStoragePriceByTimeResp %s, err: %v", queryGetSpStoragePriceByTimeResp, err) + s.Require().NoError(err) + + readPrice = queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice + readChargeRate = readPrice.MulInt(sdk.NewIntFromUint64(bucketInfo.ChargedReadQuota)).TruncateInt() + s.T().Logf("readPrice: %s, readChargeRate: %s", readPrice, readChargeRate) + taxRate = paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() + userTotalRate = readChargeRate.Add(taxRate) + + // assertions + streamAddresses[0] = paymentAccountAddr + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), readChargeRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + + expectedOutFlows = []paymenttypes.OutFlow{ + {ToAddress: family.VirtualPaymentAddress, Rate: readChargeRate}, + {ToAddress: paymenttypes.ValidatorTaxPoolAddress.String(), Rate: taxRate}, + } + userOutFlowsResponse, err = s.Client.OutFlows(ctx, &paymenttypes.QueryOutFlowsRequest{Account: paymentAccountAddr}) + s.Require().NoError(err) + sort.Slice(userOutFlowsResponse.OutFlows, func(i, j int) bool { + return userOutFlowsResponse.OutFlows[i].ToAddress < userOutFlowsResponse.OutFlows[j].ToAddress + }) + sort.Slice(expectedOutFlows, func(i, j int) bool { + return expectedOutFlows[i].ToAddress < expectedOutFlows[j].ToAddress + }) + s.Require().Equal(expectedOutFlows, userOutFlowsResponse.OutFlows) + + // set big read price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice.MulInt64(1024 * 1024 * 1024), + FreeReadQuota: queryGetSpStoragePriceByTimeResp.SpStoragePrice.FreeReadQuota, + StorePrice: queryGetSpStoragePriceByTimeResp.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + chargedReadQuota := readQuota * 1024 * 1024 * 1024 * 1024 + msgUpdateBucketInfo := storagetypes.NewMsgUpdateBucketInfo( + user.GetAddr(), bucketName, &chargedReadQuota, paymentAcc, storagetypes.VISIBILITY_TYPE_PRIVATE) + s.SendTxBlockWithExpectErrorString(msgUpdateBucketInfo, user, "apply user flows list failed") + // new payment account balance not enough + paymentAccountAddr = s.CreatePaymentAccount(user, 1, 13) + paymentAcc, err = sdk.AccAddressFromHexUnsafe(paymentAccountAddr) + msgUpdateBucketInfo = storagetypes.NewMsgUpdateBucketInfo( + user.GetAddr(), bucketName, &readQuota, paymentAcc, storagetypes.VISIBILITY_TYPE_PRIVATE) + + s.SendTxBlockWithExpectErrorString(msgUpdateBucketInfo, user, "apply user flows list failed") + +} +func (s *PaymentTestSuite) RecoverSPPrice(sp *core.StorageProvider) { + ctx := context.Background() + + queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: time.Now().Unix(), + }) + s.Require().NoError(err) + recoverReadPrice, err := sdk.NewDecFromStr("0.0087") + s.Require().NoError(err) + + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: recoverReadPrice, + FreeReadQuota: queryGetSpStoragePriceByTimeResp.SpStoragePrice.FreeReadQuota, + StorePrice: queryGetSpStoragePriceByTimeResp.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + queryGetSpStoragePriceByTimeResp, err = s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: time.Now().Unix(), + }) + s.T().Logf("queryGetSpStoragePriceByTimeResp read price: %s", queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice) +} + +// CreatePaymentAccount create new payment account and return latest payment account +func (s *PaymentTestSuite) CreatePaymentAccount(user keys.KeyManager, amount, decimal int64) string { + ctx := context.Background() + // create a new payment account + msgCreatePaymentAccount := &paymenttypes.MsgCreatePaymentAccount{ + Creator: user.GetAddr().String(), + } + _ = s.SendTxBlock(user, msgCreatePaymentAccount) + // query user's payment accounts + queryGetPaymentAccountsByOwnerRequest := paymenttypes.QueryGetPaymentAccountsByOwnerRequest{ + Owner: user.GetAddr().String(), + } + paymentAccounts, err := s.Client.GetPaymentAccountsByOwner(ctx, &queryGetPaymentAccountsByOwnerRequest) + s.Require().NoError(err) + s.T().Log(paymentAccounts) + paymentAccountAddr := paymentAccounts.PaymentAccounts[len(paymentAccounts.PaymentAccounts)-1] + // charge payment account + paymentAcc, err := sdk.AccAddressFromHexUnsafe(paymentAccountAddr) + msgSend := banktypes.NewMsgSend(user.GetAddr(), paymentAcc, []sdk.Coin{{Denom: "BNB", Amount: types.NewIntFromInt64WithDecimal(amount, decimal)}}) + s.SendTxBlock(user, msgSend) + + return paymentAccountAddr +} From 5ab6d78995247ab506597be312b885ad3befd090 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Wed, 19 Jul 2023 15:34:53 +0800 Subject: [PATCH 16/33] add e2e cases for discontinue --- deployment/localup/localup.sh | 2 +- e2e/tests/payment_test.go | 795 +++++++++++++++++++++++++++++- x/payment/keeper/stream_record.go | 1 - 3 files changed, 771 insertions(+), 27 deletions(-) diff --git a/deployment/localup/localup.sh b/deployment/localup/localup.sh index 690da86c7..b26155a61 100644 --- a/deployment/localup/localup.sh +++ b/deployment/localup/localup.sh @@ -150,7 +150,7 @@ function generate_genesis() { sed -i -e "s/\"heartbeat_interval\": \"1000\"/\"heartbeat_interval\": \"100\"/g" ${workspace}/.local/validator${i}/config/genesis.json sed -i -e "s/\"attestation_inturn_interval\": \"120\"/\"attestation_inturn_interval\": \"10\"/g" ${workspace}/.local/validator${i}/config/genesis.json sed -i -e "s/\"discontinue_confirm_period\": \"604800\"/\"discontinue_confirm_period\": \"5\"/g" ${workspace}/.local/validator${i}/config/genesis.json - sed -i -e "s/\"discontinue_deletion_max\": \"10000\"/\"discontinue_deletion_max\": \"1\"/g" ${workspace}/.local/validator${i}/config/genesis.json + sed -i -e "s/\"discontinue_deletion_max\": \"10000\"/\"discontinue_deletion_max\": \"2\"/g" ${workspace}/.local/validator${i}/config/genesis.json sed -i -e "s/\"voting_period\": \"30s\"/\"voting_period\": \"10s\"/g" ${workspace}/.local/validator${i}/config/genesis.json #sed -i -e "s/\"community_tax\": \"0.020000000000000000\"/\"community_tax\": \"0\"/g" ${workspace}/.local/validator${i}/config/genesis.json sed -i -e "s/log_level = \"info\"/\log_level= \"debug\"/g" ${workspace}/.local/validator${i}/config/config.toml diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 2179ae3ed..6c9fc523e 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -2234,6 +2234,7 @@ func (s *PaymentTestSuite) TestVirtualGroup_Settle() { } func (s *PaymentTestSuite) TestVirtualGroup_SwapOut() { + ctx := context.Background() user := s.GenAndChargeAccounts(1, 1000000)[0] // create a new storage provider sp := s.BaseSuite.CreateNewStorageProvider() @@ -2270,35 +2271,41 @@ func (s *PaymentTestSuite) TestVirtualGroup_SwapOut() { } anotherSecondarySPIDs = append(anotherSecondarySPIDs, sp.Info.Id) - familyResp, err := s.Client.GlobalVirtualGroupFamilies( - context.Background(), - &virtualgrouptypes.QueryGlobalVirtualGroupFamiliesRequest{}) - s.Require().NoError(err) - anotherSPsFamilies := familyResp.GvgFamilies - s.Require().Greater(len(anotherSPsFamilies), 0) - anotherGVGID, _ := s.BaseSuite.CreateGlobalVirtualGroup(anotherSP, anotherSPsFamilies[0].Id, anotherSecondarySPIDs, 1) + anotherGVGID, _ := s.BaseSuite.CreateGlobalVirtualGroup(anotherSP, 0, anotherSecondarySPIDs, 1) - gvgResp, err := s.Client.GlobalVirtualGroup( - context.Background(), - &virtualgrouptypes.QueryGlobalVirtualGroupRequest{GlobalVirtualGroupId: anotherGVGID}) + familyResp, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{FamilyId: familyID}) + s.Require().NoError(err) + gvgResp, err := s.Client.GlobalVirtualGroup(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupRequest{GlobalVirtualGroupId: anotherGVGID}) s.Require().NoError(err) streamAddresses := []string{ user.GetAddr().String(), - anotherSPsFamilies[0].VirtualPaymentAddress, + familyResp.GlobalVirtualGroupFamily.VirtualPaymentAddress, gvgResp.GlobalVirtualGroup.VirtualPaymentAddress, paymenttypes.ValidatorTaxPoolAddress.String(), } streamRecordsBefore := s.getStreamRecords(streamAddresses) - // sp exit + // sp exit s.SendTxBlock(sp.OperatorKey, &virtualgrouptypes.MsgStorageProviderExit{ StorageProvider: sp.OperatorKey.GetAddr().String(), }) - spResp, err := s.Client.StorageProvider(context.Background(), &sptypes.QueryStorageProviderRequest{Id: sp.Info.Id}) + resp, err := s.Client.StorageProvider(context.Background(), &sptypes.QueryStorageProviderRequest{Id: sp.Info.Id}) + s.Require().NoError(err) + s.Require().Equal(resp.StorageProvider.Status, sptypes.STATUS_GRACEFUL_EXITING) + + // swap out, as secondary sp + msgSwapOut2 := virtualgrouptypes.NewMsgSwapOut(sp.OperatorKey.GetAddr(), 0, []uint32{anotherGVGID}, successorSp.Info.Id) + msgSwapOut2.SuccessorSpApproval = &common.Approval{ExpiredHeight: math.MaxUint} + msgSwapOut2.SuccessorSpApproval.Sig, err = successorSp.ApprovalKey.Sign(msgSwapOut2.GetApprovalBytes()) + s.Require().NoError(err) + s.SendTxBlock(sp.OperatorKey, msgSwapOut2) + + // complete swap out + msgCompleteSwapOut2 := virtualgrouptypes.NewMsgCompleteSwapOut(successorSp.OperatorKey.GetAddr(), 0, []uint32{anotherGVGID}) s.Require().NoError(err) - s.Require().Equal(spResp.StorageProvider.Status, sptypes.STATUS_GRACEFUL_EXITING) + s.SendTxBlock(successorSp.OperatorKey, msgCompleteSwapOut2) // swap out, as primary sp msgSwapOut := virtualgrouptypes.NewMsgSwapOut(sp.OperatorKey.GetAddr(), familyID, nil, successorSp.Info.Id) @@ -2307,21 +2314,11 @@ func (s *PaymentTestSuite) TestVirtualGroup_SwapOut() { s.Require().NoError(err) s.SendTxBlock(sp.OperatorKey, msgSwapOut) + // complete swap out, as primary sp msgCompleteSwapOut := virtualgrouptypes.NewMsgCompleteSwapOut(successorSp.OperatorKey.GetAddr(), familyID, nil) s.Require().NoError(err) s.SendTxBlock(successorSp.OperatorKey, msgCompleteSwapOut) - // swap out again, as secondary sp - msgSwapOut2 := virtualgrouptypes.NewMsgSwapOut(sp.OperatorKey.GetAddr(), 0, []uint32{anotherGVGID}, successorSp.Info.Id) - msgSwapOut2.SuccessorSpApproval = &common.Approval{ExpiredHeight: math.MaxUint} - msgSwapOut2.SuccessorSpApproval.Sig, err = successorSp.ApprovalKey.Sign(msgSwapOut2.GetApprovalBytes()) - s.Require().NoError(err) - s.SendTxBlock(sp.OperatorKey, msgSwapOut2) - - // complete swap out - msgCompleteSwapOut2 := virtualgrouptypes.NewMsgCompleteSwapOut(successorSp.OperatorKey.GetAddr(), 0, []uint32{anotherGVGID}) - s.SendTxBlock(successorSp.OperatorKey, msgCompleteSwapOut2) - // sp complete exit success s.SendTxBlock( sp.OperatorKey, @@ -2337,6 +2334,754 @@ func (s *PaymentTestSuite) TestVirtualGroup_SwapOut() { s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) } +func (s *PaymentTestSuite) TestDiscontinue_InOneBlock_WithoutPriceChange() { + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // create bucket + bucketName := s.createBucket(sp, user, 0) + + // create & seal objects + _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) + _ = s.sealObject(bucketName, objectName1, objectId1, checksums1) + + // for payment + time.Sleep(2 * time.Second) + + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)), + )) + + simulateResponse := s.SimulateTx(msgSend, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))))), + ) + s.SendTxBlock(user, msgSend) + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) + + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + + // force delete bucket + msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") + txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) + deleteAt := filterDiscontinueBucketEventFromTx(txRes).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, deleteAt) + + if blockTime > deleteAt { + break + } + } + + _, err = s.Client.HeadBucket(ctx, &storagetypes.QueryHeadBucketRequest{BucketName: bucketName}) + s.Require().ErrorContains(err, "No such bucket") + + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) +} + +func (s *PaymentTestSuite) TestDiscontinue_InOneBlock_WithPriceChange() { + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // query storage price + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: 0, + }) + s.Require().NoError(err) + s.T().Log("price", priceRes.SpStoragePrice) + + // create bucket + bucketName := s.createBucket(sp, user, 1200987) + + // create & seal objects + _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName1, objectId1, checksums1) + + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + // for payment + time.Sleep(2 * time.Second) + + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)), + )) + + simulateResponse := s.SimulateTx(msgSend, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))))), + ) + s.SendTxBlock(user, msgSend) + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) + + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + + // force delete bucket + msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") + txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) + deleteAt := filterDiscontinueBucketEventFromTx(txRes).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, deleteAt) + + if blockTime > deleteAt { + break + } + } + + _, err = s.Client.HeadBucket(ctx, &storagetypes.QueryHeadBucketRequest{BucketName: bucketName}) + s.Require().ErrorContains(err, "No such bucket") + + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // revert price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) +} + +func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithoutPriceChange() { + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // create bucket + bucketName := s.createBucket(sp, user, 12780) + + // create & seal objects + for i := 0; i < 4; i++ { + _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) + _ = s.sealObject(bucketName, objectName1, objectId1, checksums1) + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + } + + // for payment + time.Sleep(2 * time.Second) + + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)), + )) + + simulateResponse := s.SimulateTx(msgSend, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))))), + ) + s.SendTxBlock(user, msgSend) + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) + + // force delete bucket + msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") + txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) + deleteAt := filterDiscontinueBucketEventFromTx(txRes).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, deleteAt) + + if blockTime > deleteAt { + break + } + } + + _, err = s.Client.HeadBucket(ctx, &storagetypes.QueryHeadBucketRequest{BucketName: bucketName}) + s.Require().ErrorContains(err, "No such bucket") + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) +} + +func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChange() { + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // query storage price + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: 0, + }) + s.Require().NoError(err) + s.T().Log("price", priceRes.SpStoragePrice) + + // create bucket + bucketName := s.createBucket(sp, user, 0) + + // create objects + for i := 0; i < 2; i++ { + _, _, objectName1, _, _, _ := s.createObject(user, bucketName, false) + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_CREATED) + } + + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + // create & seal objects + for i := 0; i < 2; i++ { + _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName1, objectId1, checksums1) + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + } + + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)), + )) + + simulateResponse := s.SimulateTx(msgSend, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))))), + ) + s.SendTxBlock(user, msgSend) + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) + + // for payment + time.Sleep(2 * time.Second) + + // force delete bucket + msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") + txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) + deleteAt := filterDiscontinueBucketEventFromTx(txRes).DeleteAt + + // update new price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice.MulInt64(100), + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + 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, deleteAt) + + if blockTime > deleteAt { + break + } + } + + _, err = s.Client.HeadBucket(ctx, &storagetypes.QueryHeadBucketRequest{BucketName: bucketName}) + s.Require().ErrorContains(err, "No such bucket") + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // revert price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) +} + +func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeChange() { + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // query storage price + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: 0, + }) + s.Require().NoError(err) + s.T().Log("price", priceRes.SpStoragePrice) + + // create bucket + bucketName := s.createBucket(sp, user, 0) + + // create objects + for i := 0; i < 2; i++ { + _, _, objectName1, _, _, _ := s.createObject(user, bucketName, false) + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_CREATED) + } + + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + // create & seal objects + for i := 0; i < 2; i++ { + _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName1, objectId1, checksums1) + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + } + + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)), + )) + + simulateResponse := s.SimulateTx(msgSend, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))))), + ) + s.SendTxBlock(user, msgSend) + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) + + // update params + queryParamsRequest := paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + params := queryParamsResponse.GetParams() + oldReserveTime := params.VersionedParams.ReserveTime + oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate + s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) + + params.VersionedParams.ReserveTime = oldReserveTime * 2 + params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) + + s.updateParams(params) + queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + params = queryParamsResponse.GetParams() + s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) + + // for payment + time.Sleep(2 * time.Second) + + // force delete bucket + msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") + txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) + deleteAt := filterDiscontinueBucketEventFromTx(txRes).DeleteAt + + // update new price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice.MulInt64(100), + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + 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, deleteAt) + + if blockTime > deleteAt { + break + } + } + + _, err = s.Client.HeadBucket(ctx, &storagetypes.QueryHeadBucketRequest{BucketName: bucketName}) + s.Require().ErrorContains(err, "No such bucket") + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // revert price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + // revert params + params.VersionedParams.ReserveTime = oldReserveTime + params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate + s.updateParams(params) +} + +func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeChange_FrozenAccount() { + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + // params + queryParamsRequest := paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + params := queryParamsResponse.GetParams() + oldReserveTime := params.VersionedParams.ReserveTime + oldForceSettleTime := params.ForcedSettleTime + oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate + s.T().Log("params", core.YamlString(params)) + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) + + // query storage price + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: 0, + }) + s.Require().NoError(err) + s.T().Log("price", priceRes.SpStoragePrice) + + // create bucket + bucketName := s.createBucket(sp, user, 0) + + // create objects + for i := 0; i < 2; i++ { + _, _, objectName1, _, _, _ := s.createObject(user, bucketName, false) + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_CREATED) + } + + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + // update params + params.VersionedParams.ReserveTime = 8 + params.ForcedSettleTime = 5 + s.updateParams(params) + + // create & seal objects + for i := 0; i < 2; i++ { + _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) + s.sealObject(bucketName, objectName1, objectId1, checksums1) + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: bucketName, + ObjectName: objectName1, + } + queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + } + + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + + msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)), + )) + + simulateResponse := s.SimulateTx(msgSend, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))))), + ) + s.SendTxBlock(user, msgSend) + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) + s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) + + // wait account to be frozen + time.Sleep(8 * time.Second) + streamRecord := s.getStreamRecord(user.GetAddr().String()) + s.Require().True(streamRecord.Status == paymenttypes.STREAM_ACCOUNT_STATUS_FROZEN) + + // update params + params.VersionedParams.ReserveTime = oldReserveTime * 2 + params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) + + s.updateParams(params) + queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + params = queryParamsResponse.GetParams() + s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) + + // for payment + time.Sleep(2 * time.Second) + + // force delete bucket + msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") + txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) + deleteAt := filterDiscontinueBucketEventFromTx(txRes).DeleteAt + + // update new price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice.MulInt64(100), + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + 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, deleteAt) + + if blockTime > deleteAt { + break + } + } + + _, err = s.Client.HeadBucket(ctx, &storagetypes.QueryHeadBucketRequest{BucketName: bucketName}) + s.Require().ErrorContains(err, "No such bucket") + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // revert price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + // revert params + params.VersionedParams.ReserveTime = oldReserveTime + params.ForcedSettleTime = oldForceSettleTime + params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate + s.updateParams(params) +} + func TestPaymentTestSuite(t *testing.T) { suite.Run(t, new(PaymentTestSuite)) } diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index 692371359..6d41c9c98 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -142,7 +142,6 @@ func (k Keeper) UpdateStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe if currentTimestamp != timestamp { if !streamRecord.NetflowRate.IsZero() { flowDelta := streamRecord.NetflowRate.MulRaw(currentTimestamp - timestamp) - fmt.Println("flowDelta", flowDelta.String()) streamRecord.StaticBalance = streamRecord.StaticBalance.Add(flowDelta) } streamRecord.CrudTimestamp = currentTimestamp From cefaa0b1669909a08e958daeb6ba180015c3fc1d Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Thu, 20 Jul 2023 08:40:54 +0800 Subject: [PATCH 17/33] try to make tests stable --- deployment/localup/localup.sh | 2 +- e2e/core/basesuite.go | 9 +++ e2e/tests/payment_test.go | 127 ++++++++++++++++----------------- e2e/tests/storage_bill_test.go | 8 +-- 4 files changed, 74 insertions(+), 72 deletions(-) diff --git a/deployment/localup/localup.sh b/deployment/localup/localup.sh index b26155a61..df7eb776e 100644 --- a/deployment/localup/localup.sh +++ b/deployment/localup/localup.sh @@ -151,7 +151,7 @@ function generate_genesis() { sed -i -e "s/\"attestation_inturn_interval\": \"120\"/\"attestation_inturn_interval\": \"10\"/g" ${workspace}/.local/validator${i}/config/genesis.json sed -i -e "s/\"discontinue_confirm_period\": \"604800\"/\"discontinue_confirm_period\": \"5\"/g" ${workspace}/.local/validator${i}/config/genesis.json sed -i -e "s/\"discontinue_deletion_max\": \"10000\"/\"discontinue_deletion_max\": \"2\"/g" ${workspace}/.local/validator${i}/config/genesis.json - sed -i -e "s/\"voting_period\": \"30s\"/\"voting_period\": \"10s\"/g" ${workspace}/.local/validator${i}/config/genesis.json + sed -i -e "s/\"voting_period\": \"30s\"/\"voting_period\": \"1s\"/g" ${workspace}/.local/validator${i}/config/genesis.json #sed -i -e "s/\"community_tax\": \"0.020000000000000000\"/\"community_tax\": \"0\"/g" ${workspace}/.local/validator${i}/config/genesis.json sed -i -e "s/log_level = \"info\"/\log_level= \"debug\"/g" ${workspace}/.local/validator${i}/config/config.toml done diff --git a/e2e/core/basesuite.go b/e2e/core/basesuite.go index 0cb59b14a..c14485a96 100644 --- a/e2e/core/basesuite.go +++ b/e2e/core/basesuite.go @@ -641,6 +641,15 @@ func (s *BaseSuite) PickStorageProvider() *StorageProvider { return nil } +func (s *BaseSuite) PickDifferentStorageProvider(spId uint32) *StorageProvider { + for _, sp := range s.StorageProviders { + if sp.Info.Id != spId { + return sp + } + } + return nil +} + func (s *BaseSuite) PickStorageProviderByBucketName(bucketName string) *StorageProvider { queryHeadBucketResponse, err := s.Client.HeadBucket(context.Background(), &storagetypes.QueryHeadBucketRequest{ BucketName: bucketName, diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 6c9fc523e..1c8fdc0b0 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -47,7 +47,9 @@ func (s *PaymentTestSuite) SetupSuite() { s.BaseSuite.SetupSuite() } -func (s *PaymentTestSuite) SetupTest() {} +func (s *PaymentTestSuite) SetupTest() { + s.RefreshGVGFamilies() +} func (s *PaymentTestSuite) TestCreatePaymentAccount() { user := s.GenAndChargeAccounts(1, 100)[0] @@ -93,6 +95,8 @@ func (s *PaymentTestSuite) TestCreatePaymentAccount() { func (s *PaymentTestSuite) TestVersionedParams_SealObjectAfterReserveTimeChange() { ctx := context.Background() sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) queryParamsRequest := paymenttypes.QueryParamsRequest{} queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) s.Require().NoError(err) @@ -116,7 +120,7 @@ func (s *PaymentTestSuite) TestVersionedParams_SealObjectAfterReserveTimeChange( s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) // seal object - s.sealObject(bucketName, objectName, objectId, checksums) + s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ BucketName: bucketName, @@ -146,6 +150,8 @@ func (s *PaymentTestSuite) TestVersionedParams_SealObjectAfterReserveTimeChange( func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRateChange() { ctx := context.Background() sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) queryParamsRequest := paymenttypes.QueryParamsRequest{} queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) s.Require().NoError(err) @@ -165,7 +171,7 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRate user, bucketName, objectName, objectId, checksums := s.createBucketAndObject(sp) // seal object - s.sealObject(bucketName, objectName, objectId, checksums) + s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) // update params params := queryParamsResponse.GetParams() @@ -208,6 +214,8 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRate func (s *PaymentTestSuite) TestVersionedParams_DeleteObjectAfterReserveTimeChange() { ctx := context.Background() sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) queryParamsRequest := paymenttypes.QueryParamsRequest{} queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) s.Require().NoError(err) @@ -216,7 +224,7 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteObjectAfterReserveTimeChang user, bucketName, objectName, objectId, checksums := s.createBucketAndObject(sp) // seal object - s.sealObject(bucketName, objectName, objectId, checksums) + s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) // for payment time.Sleep(2 * time.Second) @@ -661,7 +669,6 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { s.T().Logf("paymentParams %s, err: %v", paymentParams, err) s.Require().NoError(err) reserveTime := paymentParams.Params.VersionedParams.ReserveTime - forcedSettleTime := paymentParams.Params.ForcedSettleTime queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ SpAddr: sp.OperatorKey.GetAddr().String(), }) @@ -707,6 +714,8 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { s.Require().Equal(expectedRate.String(), paymentAccountStreamRecord.NetflowRate.Neg().String()) s.Require().Equal(paymentAccountStreamRecord.BufferBalance.String(), paymentAccountBNBNeeded.String()) s.Require().Equal(paymentAccountStreamRecord.StaticBalance.String(), sdkmath.ZeroInt().String()) + govStreamRecord := s.getStreamRecord(paymenttypes.GovernanceAddress.String()) + s.T().Logf("govStreamRecord %s", core.YamlString(govStreamRecord)) // increase bucket charged read quota is not allowed since the balance is not enough msgUpdateBucketInfo := &storagetypes.MsgUpdateBucketInfo{ @@ -715,27 +724,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { ChargedReadQuota: &common.UInt64Value{Value: bucketChargedReadQuota + 1}, Visibility: storagetypes.VISIBILITY_TYPE_PUBLIC_READ, } - _, err = s.SendTxBlockWithoutCheck(msgUpdateBucketInfo, user) - s.Require().ErrorContains(err, "balance not enough, lack of") - - // create bucket from user - msgCreateBucket.BucketName = storagetestutils.GenRandomBucketName() - msgCreateBucket.PaymentAddress = "" - msgCreateBucket.PrimarySpApproval.GlobalVirtualGroupFamilyId = gvg.FamilyId - msgCreateBucket.PrimarySpApproval.Sig, err = sp.ApprovalKey.Sign(msgCreateBucket.GetApprovalBytes()) - s.Require().NoError(err) - s.SendTxBlock(user, msgCreateBucket) - - // check user stream record - userStreamRecord := s.getStreamRecord(userAddr) - s.T().Logf("userStreamRecord %s", core.YamlString(userStreamRecord)) - s.Require().Equal(userStreamRecord.SettleTimestamp, userStreamRecord.CrudTimestamp+int64(reserveTime-forcedSettleTime)) - familyStreamRecord := s.getStreamRecord(family.VirtualPaymentAddress) - s.T().Logf("familyStreamRecord %s", core.YamlString(familyStreamRecord)) - govStreamRecord := s.getStreamRecord(paymenttypes.GovernanceAddress.String()) - s.T().Logf("govStreamRecord %s", core.YamlString(govStreamRecord)) - paymentStreamRecord := s.getStreamRecord(paymentAddr) - s.T().Logf("paymentStreamRecord %s", core.YamlString(paymentStreamRecord)) + s.SendTxBlockWithExpectErrorString(msgUpdateBucketInfo, user, "balance not enough, lack of") // wait until settle time retryCount := 0 @@ -743,8 +732,8 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { latestBlock, err := s.TmClient.TmClient.Block(ctx, nil) s.Require().NoError(err) currentTimestamp := latestBlock.Block.Time.Unix() - s.T().Logf("currentTimestamp %d, userStreamRecord.SettleTimestamp %d", currentTimestamp, userStreamRecord.SettleTimestamp) - if currentTimestamp > userStreamRecord.SettleTimestamp { + s.T().Logf("currentTimestamp %d, userStreamRecord.SettleTimestamp %d", currentTimestamp, paymentAccountStreamRecord.SettleTimestamp) + if currentTimestamp > paymentAccountStreamRecord.SettleTimestamp { break } time.Sleep(time.Second) @@ -764,16 +753,13 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { s.Require().NotEqual(paymentAccountStreamRecordAfterAutoSettle.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) s.Require().Equal(familyStreamRecordAfterAutoSettle.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) s.Require().Equal(userStreamRecordAfterAutoSettle.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) - // user settle time become refreshed - s.Require().NotEqual(userStreamRecordAfterAutoSettle.SettleTimestamp, userStreamRecord.SettleTimestamp) - s.Require().Equal(userStreamRecordAfterAutoSettle.SettleTimestamp, userStreamRecordAfterAutoSettle.CrudTimestamp+int64(reserveTime-forcedSettleTime)) - // gov stream record balance increase + govStreamRecordAfterSettle := s.getStreamRecord(paymenttypes.GovernanceAddress.String()) s.T().Logf("govStreamRecordAfterSettle %s", core.YamlString(govStreamRecordAfterSettle)) s.Require().NotEqual(govStreamRecordAfterSettle.StaticBalance.String(), govStreamRecord.StaticBalance.String()) govStreamRecordStaticBalanceDelta := govStreamRecordAfterSettle.StaticBalance.Sub(govStreamRecord.StaticBalance) - expectedGovBalanceDelta := paymentStreamRecord.NetflowRate.Neg().MulRaw(paymentAccountStreamRecordAfterAutoSettle.CrudTimestamp - paymentStreamRecord.CrudTimestamp) - s.Require().Equal(expectedGovBalanceDelta.String(), govStreamRecordStaticBalanceDelta.String()) + expectedGovBalanceDelta := paymentAccountStreamRecord.NetflowRate.Neg().MulRaw(paymentAccountStreamRecordAfterAutoSettle.CrudTimestamp - paymentAccountStreamRecord.CrudTimestamp) + s.Require().True(govStreamRecordStaticBalanceDelta.Int64() >= expectedGovBalanceDelta.Int64()) // deposit, balance not enough to resume depositAmount1 := sdk.NewInt(1) @@ -936,7 +922,7 @@ func (s *PaymentTestSuite) TestWithdraw() { s.T().Logf("queryGetSpStoragePriceByTimeResp %s, err: %v", queryGetSpStoragePriceByTimeResp, err) s.Require().NoError(err) - bucketChargedReadQuota := uint64(1000) + bucketChargedReadQuota := uint64(100000) readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice totalUserRate := readPrice.MulInt(sdkmath.NewIntFromUint64(bucketChargedReadQuota)).TruncateInt() taxRateParam := params.Params.VersionedParams.ValidatorTaxRate @@ -1267,6 +1253,8 @@ func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WhenPaymentAc ctx := context.Background() user := s.GenAndChargeAccounts(1, 1000000)[0] sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) queryParamsRequest := paymenttypes.QueryParamsRequest{} queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) @@ -1285,10 +1273,10 @@ func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WhenPaymentAc // create & seal objects _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName1, objectId1, checksums1) + s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) _, _, objectName2, objectId2, checksums2, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName2, objectId2, checksums2) + s.sealObject(sp, gvg, bucketName, objectName2, objectId2, checksums2) queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) @@ -1359,6 +1347,9 @@ func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WithPriceChan // set storage price sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ SpAddr: sp.OperatorKey.GetAddr().String(), Timestamp: 0, @@ -1372,10 +1363,10 @@ func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WithPriceChan // create & seal objects _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName1, objectId1, checksums1) + s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) _, _, objectName2, objectId2, checksums2, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName2, objectId2, checksums2) + s.sealObject(sp, gvg, bucketName, objectName2, objectId2, checksums2) // update new price msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ @@ -1485,7 +1476,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithoutPriceChange // create & seal objects _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName1, objectId1, checksums1) + s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) // for payment time.Sleep(2 * time.Second) @@ -1572,7 +1563,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() // create & seal objects _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName1, objectId1, checksums1) + s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) // for payment time.Sleep(2 * time.Second) @@ -1673,7 +1664,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreLessThanReserve // create & seal objects _, _, objectName1, objectId1, checksums1, payloadSize := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName1, objectId1, checksums1) + s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) headObjectRes, err := s.Client.HeadObject(ctx, &storagetypes.QueryHeadObjectRequest{ BucketName: bucketName, @@ -1744,7 +1735,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreMoreThanReserve // create & seal objects _, _, objectName1, objectId1, checksums1, payloadSize := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName1, objectId1, checksums1) + s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) headObjectRes, err := s.Client.HeadObject(ctx, &storagetypes.QueryHeadObjectRequest{ BucketName: bucketName, @@ -2045,7 +2036,7 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithoutPriceChange() { s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) // case: seal object without price change - s.sealObject(bucketName, objectName, objectId, checksums) + s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) // assertions streamRecordsAfter = s.getStreamRecords(streamAddresses) @@ -2103,7 +2094,7 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChange() { streamRecordsBefore := s.getStreamRecords(streamAddresses) gvgFamilyRateReadBefore, taxRateReadBefore, userTotalRateReadBefore := s.calculateReadRates(sp, bucketName) - s.sealObject(bucketName, objectName, objectId, checksums) + s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) // assertions streamRecordsAfter := s.getStreamRecords(streamAddresses) @@ -2144,13 +2135,13 @@ func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { bucketName1 := s.createBucket(sp, user, 0) _, _, objectName1, _, _, _ := s.createObject(user, bucketName1, true) _, _, objectName2, objectId2, checksums2, _ := s.createObject(user, bucketName1, false) - s.sealObject(bucketName1, objectName2, objectId2, checksums2) + s.sealObject(sp, gvg, bucketName1, objectName2, objectId2, checksums2) bucketName2 := s.createBucket(sp, user, 1024) _, _, objectName3, objectId3, checksums3, _ := s.createObject(user, bucketName2, false) - s.sealObject(bucketName2, objectName3, objectId3, checksums3) + s.sealObject(sp, gvg, bucketName2, objectName3, objectId3, checksums3) _, _, objectName4, objectId4, checksums4, _ := s.createObject(user, bucketName2, false) - s.sealObject(bucketName2, objectName4, objectId4, checksums4) + s.sealObject(sp, gvg, bucketName2, objectName4, objectId4, checksums4) time.Sleep(3 * time.Second) @@ -2187,7 +2178,7 @@ func (s *PaymentTestSuite) TestVirtualGroup_Settle() { bucketName := s.createBucket(sp, user, 1024) _, _, objectName, objectId, checksums, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName, objectId, checksums) + s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) // sleep seconds time.Sleep(3 * time.Second) @@ -2236,12 +2227,12 @@ func (s *PaymentTestSuite) TestVirtualGroup_Settle() { func (s *PaymentTestSuite) TestVirtualGroup_SwapOut() { ctx := context.Background() user := s.GenAndChargeAccounts(1, 1000000)[0] + successorSp := s.PickStorageProvider() + // create a new storage provider sp := s.BaseSuite.CreateNewStorageProvider() s.T().Logf("new SP Info: %s", sp.Info.String()) - successorSp := s.PickStorageProvider() - // create a new gvg group for this storage provider var secondarySPIDs []uint32 for _, ssp := range s.StorageProviders { @@ -2259,7 +2250,7 @@ func (s *PaymentTestSuite) TestVirtualGroup_SwapOut() { s.BaseSuite.CreateObject(user, sp, gvgID, storagetestutils.GenRandomBucketName(), storagetestutils.GenRandomObjectName()) // Create another gvg contains this new sp - anotherSP := s.StorageProviders[1] + anotherSP := s.PickDifferentStorageProvider(successorSp.Info.Id) var anotherSecondarySPIDs []uint32 for _, ssp := range s.StorageProviders { if ssp.Info.Id != successorSp.Info.Id && ssp.Info.Id != anotherSP.Info.Id { @@ -2359,7 +2350,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InOneBlock_WithoutPriceChange() { // create & seal objects _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - _ = s.sealObject(bucketName, objectName1, objectId1, checksums1) + _ = s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) // for payment time.Sleep(2 * time.Second) @@ -2454,7 +2445,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InOneBlock_WithPriceChange() { // create & seal objects _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName1, objectId1, checksums1) + s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) // update new price msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ @@ -2560,7 +2551,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithoutPriceChange() { // create & seal objects for i := 0; i < 4; i++ { _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - _ = s.sealObject(bucketName, objectName1, objectId1, checksums1) + _ = s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ BucketName: bucketName, ObjectName: objectName1, @@ -2568,6 +2559,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithoutPriceChange() { queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) s.Require().NoError(err) s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + time.Sleep(200 * time.Millisecond) } // for payment @@ -2662,6 +2654,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChange() { queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) s.Require().NoError(err) s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_CREATED) + time.Sleep(200 * time.Millisecond) } // update new price @@ -2676,7 +2669,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChange() { // create & seal objects for i := 0; i < 2; i++ { _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName1, objectId1, checksums1) + s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ BucketName: bucketName, ObjectName: objectName1, @@ -2684,6 +2677,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChange() { queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) s.Require().NoError(err) s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + time.Sleep(200 * time.Millisecond) } queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} @@ -2784,7 +2778,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh s.T().Log("price", priceRes.SpStoragePrice) // create bucket - bucketName := s.createBucket(sp, user, 0) + bucketName := s.createBucket(sp, user, 10200) // create objects for i := 0; i < 2; i++ { @@ -2796,6 +2790,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) s.Require().NoError(err) s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_CREATED) + time.Sleep(200 * time.Millisecond) } // update new price @@ -2810,7 +2805,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh // create & seal objects for i := 0; i < 2; i++ { _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName1, objectId1, checksums1) + s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ BucketName: bucketName, ObjectName: objectName1, @@ -2818,6 +2813,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) s.Require().NoError(err) s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + time.Sleep(200 * time.Millisecond) } queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} @@ -2895,7 +2891,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) - s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + s.Require().True(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64() <= int64(0)) // there are other auto settling // revert price msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ @@ -2963,6 +2959,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) s.Require().NoError(err) s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_CREATED) + time.Sleep(200 * time.Millisecond) } // update new price @@ -2982,7 +2979,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh // create & seal objects for i := 0; i < 2; i++ { _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - s.sealObject(bucketName, objectName1, objectId1, checksums1) + s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ BucketName: bucketName, ObjectName: objectName1, @@ -2990,6 +2987,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) s.Require().NoError(err) s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) + time.Sleep(200 * time.Millisecond) } queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} @@ -3064,7 +3062,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) - s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + s.Require().True(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64() <= int64(0)) // there are other auto settling // revert price msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ @@ -3503,12 +3501,7 @@ func (s *PaymentTestSuite) cancelCreateObject(user keys.KeyManager, bucketName, s.Require().Error(err) } -func (s *PaymentTestSuite) sealObject(bucketName, objectName string, objectId storagetypes.Uint, checksums [][]byte) *virtualgrouptypes.GlobalVirtualGroup { - sp := s.BaseSuite.PickStorageProviderByBucketName(bucketName) - gvg, found := sp.GetFirstGlobalVirtualGroup() - s.Require().True(found) - s.T().Log("GVG info: ", gvg.String()) - +func (s *PaymentTestSuite) sealObject(sp *core.StorageProvider, gvg *virtualgrouptypes.GlobalVirtualGroup, bucketName, objectName string, objectId storagetypes.Uint, checksums [][]byte) *virtualgrouptypes.GlobalVirtualGroup { // SealObject gvgId := gvg.Id msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, gvg.Id, nil) diff --git a/e2e/tests/storage_bill_test.go b/e2e/tests/storage_bill_test.go index 0c743b21c..a3680e890 100644 --- a/e2e/tests/storage_bill_test.go +++ b/e2e/tests/storage_bill_test.go @@ -94,7 +94,7 @@ func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithoutPriceChange() { s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) // case: seal object without price change - s.sealObject(bucketName, objectName, objectId, checksums) + s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) // assertions streamRecordsAfter = s.getStreamRecords(streamAddresses) @@ -112,7 +112,7 @@ func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithoutPriceChange() { objectIfo, err := s.copyObject(user0, sp, bucketName, objectName, distBucketName, distObjectName) s.Require().NoError(err) - s.sealObject(distBucketName, distObjectName, objectIfo.Id, objectIfo.Checksums) + s.sealObject(sp, gvg, distBucketName, distObjectName, objectIfo.Id, objectIfo.Checksums) // assertions streamRecordsAfterCopy := s.getStreamRecords(streamAddresses) s.Require().Equal(streamRecordsAfterCopy.User.StaticBalance, sdkmath.ZeroInt()) @@ -166,7 +166,7 @@ func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithPriceChange() { s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) // case: seal object without price change - s.sealObject(bucketName, objectName, objectId, checksums) + s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) // assertions streamRecordsAfter = s.getStreamRecords(streamAddresses) @@ -195,7 +195,7 @@ func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithPriceChange() { distObjectName := storagetestutils.GenRandomObjectName() objectIfo, err := s.copyObject(user0, sp, bucketName, objectName, distBucketName, distObjectName) s.Require().NoError(err) - s.sealObject(distBucketName, distObjectName, objectIfo.Id, objectIfo.Checksums) + s.sealObject(sp, gvg, distBucketName, distObjectName, objectIfo.Id, objectIfo.Checksums) // assertions streamRecordsAfterCopy := s.getStreamRecords(streamAddresses) s.Require().Equal(streamRecordsAfterCopy.User.StaticBalance, sdkmath.ZeroInt()) From 99e93884a4152e77d43636db92658df36aee2b63 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Thu, 20 Jul 2023 13:53:46 +0800 Subject: [PATCH 18/33] add tests and update logic --- e2e/tests/payment_test.go | 454 +++++++++++++++++++----------- x/payment/keeper/stream_record.go | 53 +--- x/storage/keeper/payment.go | 17 +- 3 files changed, 314 insertions(+), 210 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index fe7db60ef..80a1c7194 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -1251,198 +1251,94 @@ func (s *PaymentTestSuite) TestStorageBill_Smoke() { s.T().Logf("deleteObjectSimRes %v", deleteObjectSimRes.Result) } -func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WhenPaymentAccountFrozen() { +func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithoutPriceChange() { + var err error ctx := context.Background() - user := s.GenAndChargeAccounts(1, 1000000)[0] sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) - - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) s.Require().NoError(err) - s.T().Log("queryParamsResponse", core.YamlString(queryParamsResponse)) - oldReserveTime := queryParamsResponse.Params.VersionedParams.ReserveTime - oldForceSettleTime := queryParamsResponse.Params.ForcedSettleTime + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] - params := queryParamsResponse.Params - params.VersionedParams.ReserveTime = 5 - params.ForcedSettleTime = 2 - s.updateParams(params) + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore := s.getStreamRecords(streamAddresses) // create bucket - bucketName := s.createBucket(sp, user, 0) - - // create & seal objects - _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) - s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) - - _, _, objectName2, objectId2, checksums2, _ := s.createObject(user, bucketName, false) - s.sealObject(sp, gvg, bucketName, objectName2, objectId2, checksums2) - - queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} - queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) - s.Require().NoError(err) - - msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( - sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)), - )) + bucketName := s.createBucket(sp, user, 256) - simulateResponse := s.SimulateTx(msgSend, user) + //simulate delete bucket gas + msgDeleteBucket := storagetypes.NewMsgDeleteBucket(user.GetAddr(), bucketName) + simulateResponse := s.SimulateTx(msgDeleteBucket, user) gasLimit := simulateResponse.GasInfo.GetGasUsed() gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) s.Require().NoError(err) - msgSend.Amount = sdk.NewCoins( - sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))))), - ) - s.SendTxBlock(user, msgSend) - queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) - s.Require().NoError(err) - s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) - - queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ - BucketName: bucketName, - ObjectName: objectName1, - } - queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) - s.Require().NoError(err) - s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) - - // for freeze account - time.Sleep(5 * time.Second) - userStreamRecord := s.getStreamRecord(user.GetAddr().String()) - s.Require().True(userStreamRecord.Status == paymenttypes.STREAM_ACCOUNT_STATUS_FROZEN) - - // force delete bucket - msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") - txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) - deleteAt := filterDiscontinueBucketEventFromTx(txRes).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, deleteAt) - - if blockTime > deleteAt { - break - } - } - - _, err = s.Client.HeadBucket(ctx, &storagetypes.QueryHeadBucketRequest{BucketName: bucketName}) - s.Require().ErrorContains(err, "No such bucket") - - // revert params - params = queryParamsResponse.Params - params.VersionedParams.ReserveTime = oldReserveTime - params.ForcedSettleTime = oldForceSettleTime - s.updateParams(params) -} - -// TestStorageBill_ForceDeleteObjectBucket_WithPriceChange will cover the following case: -// create an object, sp increase the price a lot, the object can be force deleted even the object's own has no enough balance. -func (s *PaymentTestSuite) TestStorageBill_ForceDeleteObjectBucket_WithPriceChange() { - ctx := context.Background() - - // set storage price - sp := s.PickStorageProvider() - gvg, found := sp.GetFirstGlobalVirtualGroup() - s.Require().True(found) - - priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ - SpAddr: sp.OperatorKey.GetAddr().String(), - Timestamp: 0, - }) - s.Require().NoError(err) - s.T().Log("price", priceRes.SpStoragePrice) - - user := s.GenAndChargeAccounts(1, 1000000)[0] - // create bucket - bucketName := s.createBucket(sp, user, 0) + gas := gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))) + s.T().Log("total gas", "gas", gas) // create & seal objects _, _, objectName1, objectId1, checksums1, _ := s.createObject(user, bucketName, false) s.sealObject(sp, gvg, bucketName, objectName1, objectId1, checksums1) - _, _, objectName2, objectId2, checksums2, _ := s.createObject(user, bucketName, false) - s.sealObject(sp, gvg, bucketName, objectName2, objectId2, checksums2) - - // update new price - msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ - SpAddress: sp.OperatorKey.GetAddr().String(), - ReadPrice: priceRes.SpStoragePrice.ReadPrice, - FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, - StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), - } - s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) - // for payment time.Sleep(2 * time.Second) - queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} - queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) - s.Require().NoError(err) - + //transfer gas msgSend := banktypes.NewMsgSend(user.GetAddr(), core.GenRandomAddr(), sdk.NewCoins( - sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)), + sdk.NewCoin(s.Config.Denom, sdkmath.NewInt(5*types.DecimalGwei)), )) - - simulateResponse := s.SimulateTx(msgSend, user) - gasLimit := simulateResponse.GasInfo.GetGasUsed() - gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + simulateResponse = s.SimulateTx(msgSend, user) + gasLimit = simulateResponse.GasInfo.GetGasUsed() + gasPrice, err = sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) s.Require().NoError(err) - msgSend.Amount = sdk.NewCoins( - sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit))))), - ) - s.SendTxBlock(user, msgSend) - queryBalanceResponse, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) - s.Require().NoError(err) - s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) + gas = gas.Add(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit)))) + s.T().Log("total gas", "gas", gas) - queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ - BucketName: bucketName, - ObjectName: objectName1, - } - queryHeadObjectResponse, err := s.Client.HeadObject(ctx, &queryHeadObjectRequest) + //delete object gas + msgDeleteObject := storagetypes.NewMsgDeleteObject(user.GetAddr(), bucketName, objectName1) + simulateResponse = s.SimulateTx(msgDeleteObject, user) + gasLimit = simulateResponse.GasInfo.GetGasUsed() + gasPrice, err = sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) s.Require().NoError(err) - s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) - // force delete bucket - msgDiscontinueBucket := storagetypes.NewMsgDiscontinueBucket(sp.GcKey.GetAddr(), bucketName, "test") - txRes := s.SendTxBlock(sp.GcKey, msgDiscontinueBucket) - deleteAt := filterDiscontinueBucketEventFromTx(txRes).DeleteAt - - for { - time.Sleep(200 * time.Millisecond) - statusRes, err := s.TmClient.TmClient.Status(context.Background()) - s.Require().NoError(err) - blockTime := statusRes.SyncInfo.LatestBlockTime.Unix() + gas = gas.Add(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit)))) + s.T().Log("total gas", "gas", gas) - s.T().Logf("current blockTime: %d, delete blockTime: %d", blockTime, deleteAt) + // transfer out user's balance + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) - if blockTime > deleteAt { - break - } - } + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.Sub(gas)), + ) + s.SendTxBlock(user, msgSend) + _, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) + s.Require().NoError(err) - _, err = s.Client.HeadBucket(ctx, &storagetypes.QueryHeadBucketRequest{BucketName: bucketName}) - s.Require().ErrorContains(err, "No such bucket") + s.SendTxBlock(user, msgDeleteObject) + s.SendTxBlock(user, msgDeleteBucket) - // revert price - msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ - SpAddress: sp.OperatorKey.GetAddr().String(), - ReadPrice: priceRes.SpStoragePrice.ReadPrice, - FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, - StorePrice: priceRes.SpStoragePrice.StorePrice, - } - s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.NetflowRate, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) } -func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithoutPriceChange() { +func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() { var err error ctx := context.Background() sp := s.PickStorageProvider() @@ -1517,6 +1413,23 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithoutPriceChange _, err = s.Client.BankQueryClient.Balance(ctx, &queryBalanceRequest) s.Require().NoError(err) + // sp price changes + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: 0, + }) + s.Require().NoError(err) + s.T().Log("price", priceRes.SpStoragePrice) + + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice.MulInt64(1000), + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + s.SendTxBlock(user, msgDeleteObject) s.SendTxBlock(user, msgDeleteBucket) @@ -1527,9 +1440,18 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithoutPriceChange s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // revert price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) } -func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() { +func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChangeReserveTimeChange() { var err error ctx := context.Background() sp := s.PickStorageProvider() @@ -1621,6 +1543,24 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() } s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + // update params + queryParamsRequest := paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + params := queryParamsResponse.GetParams() + oldReserveTime := params.VersionedParams.ReserveTime + oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate + s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) + + params.VersionedParams.ReserveTime = oldReserveTime * 2 + params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) + + s.updateParams(params) + queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + params = queryParamsResponse.GetParams() + s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) + s.SendTxBlock(user, msgDeleteObject) s.SendTxBlock(user, msgDeleteBucket) @@ -1640,6 +1580,12 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() StorePrice: priceRes.SpStoragePrice.StorePrice, } s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + // revert params + params = queryParamsResponse.Params + params.VersionedParams.ReserveTime = oldReserveTime + params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate + s.updateParams(params) } func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreLessThanReserveTime() { @@ -1944,6 +1890,85 @@ func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithZeroNoneZeroPayload( s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) } +func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithReserveTimeValidatorTaxRateChange() { + var err error + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + bucketName := s.createBucket(sp, user, 0) + + // create object with none zero payload size + streamRecordsBefore := s.getStreamRecords(streamAddresses) + _, _, objectName, _, _, payloadSize := s.createObject(user, bucketName, false) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + lockFee := s.calculateLockFee(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.LockBalance.Sub(streamRecordsBefore.User.LockBalance), lockFee) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // update params + queryParamsRequest := paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + params := queryParamsResponse.GetParams() + oldReserveTime := params.VersionedParams.ReserveTime + oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate + s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) + + params.VersionedParams.ReserveTime = oldReserveTime * 2 + params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) + + s.updateParams(params) + queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + params = queryParamsResponse.GetParams() + s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) + + // create another object after parameter changes + streamRecordsBefore = s.getStreamRecords(streamAddresses) + _, _, objectName, _, _, payloadSize = s.createObject(user, bucketName, false) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + lockFeeAfterParameterChange := s.calculateLockFee(sp, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.LockBalance.Sub(streamRecordsBefore.User.LockBalance), lockFeeAfterParameterChange) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + s.Require().True(lockFeeAfterParameterChange.GT(lockFee.MulRaw(2))) + + // revert params + params.VersionedParams.ReserveTime = oldReserveTime + params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate + s.updateParams(params) +} + func (s *PaymentTestSuite) TestStorageBill_CancelCreateObject() { var err error ctx := context.Background() @@ -2096,6 +2121,8 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChange() { streamRecordsBefore := s.getStreamRecords(streamAddresses) gvgFamilyRateReadBefore, taxRateReadBefore, userTotalRateReadBefore := s.calculateReadRates(sp, bucketName) + + // seal object s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) // assertions @@ -2112,6 +2139,113 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChange() { s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRateReadAfter.Sub(taxRateReadBefore).Add(taxRateStore)) } +func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChangeValidatorTaxRateChange() { + var err error + ctx := context.Background() + sp := s.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + bucketName := s.createBucket(sp, user, 102400) + + // case: seal object with read price change and storage price change + _, _, objectName, objectId, checksums, payloadSize := s.createObject(user, bucketName, false) + + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: 0, + }) + s.Require().NoError(err) + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice.MulInt64(2), + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(2), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + streamRecordsBefore := s.getStreamRecords(streamAddresses) + gvgFamilyRateReadBefore, taxRateReadBefore, userTotalRateReadBefore := s.calculateReadRates(sp, bucketName) + + // seal object + s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + gvgFamilyRateReadAfter, taxRateReadAfter, userTotalRateReadAfter := s.calculateReadRatesCurrentTimestamp(sp, bucketName) + gvgFamilyRateStore, gvgRateStore, taxRateStore, userTotalRateStore := s.calculateStorageRatesCurrentTimestamp(sp, bucketName, objectName, payloadSize) + + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) + + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRateReadAfter.Sub(userTotalRateReadBefore).Add(userTotalRateStore).Neg()) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRateStore) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRateReadAfter.Sub(gvgFamilyRateReadBefore).Add(gvgFamilyRateStore)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRateReadAfter.Sub(taxRateReadBefore).Add(taxRateStore)) + + // update params + queryParamsRequest := paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + params := queryParamsResponse.GetParams() + oldReserveTime := params.VersionedParams.ReserveTime + oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate + s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) + + params.VersionedParams.ReserveTime = oldReserveTime * 2 + params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) + + s.updateParams(params) + queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + params = queryParamsResponse.GetParams() + s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) + + _, _, objectName, objectId, checksums, payloadSize = s.createObject(user, bucketName, false) + s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + gvgFamilyRateReadAfter, taxRateReadAfter, userTotalRateReadAfter = s.calculateReadRatesCurrentTimestamp(sp, bucketName) + gvgFamilyRateStore, gvgRateStore, taxRateStore, userTotalRateStore = s.calculateStorageRatesCurrentTimestamp(sp, bucketName, objectName, payloadSize) + + gvgFamilyRateStore = gvgFamilyRateStore.MulRaw(2) + gvgRateStore = gvgRateStore.MulRaw(2) + taxRateStore = taxRateStore.MulRaw(2) + userTotalRateStore = userTotalRateStore.MulRaw(2) + + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) + + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRateReadAfter.Sub(userTotalRateReadBefore).Add(userTotalRateStore).Neg()) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRateStore) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRateReadAfter.Sub(gvgFamilyRateReadBefore).Add(gvgFamilyRateStore)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRateReadAfter.Sub(taxRateReadBefore).Add(taxRateStore)) + + // revert params + params.VersionedParams.ReserveTime = oldReserveTime + params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate + s.updateParams(params) +} + func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { var err error ctx := context.Background() @@ -2615,6 +2749,8 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithoutPriceChange() { s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) } +// TestDiscontinue_InBlocks_WithPriceChange will cover the following case: +// create an object, sp increase the price a lot, the object can be force deleted even the object's own has no enough balance. func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChange() { ctx := context.Background() sp := s.PickStorageProvider() diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index 6d41c9c98..42efce7f3 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -146,7 +146,6 @@ func (k Keeper) UpdateStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe } streamRecord.CrudTimestamp = currentTimestamp } - // update lock balance if !change.LockBalanceChange.IsZero() { streamRecord.LockBalance = streamRecord.LockBalance.Add(change.LockBalanceChange) @@ -196,57 +195,15 @@ func (k Keeper) UpdateStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe if !forced { return fmt.Errorf("stream account %s lacks of %s BNB", streamRecord.Account, streamRecord.StaticBalance.Abs()) } - } - settleTimestamp = currentTimestamp - int64(params.ForcedSettleTime) + payDuration.Int64() - } - k.UpdateAutoSettleRecord(ctx, sdk.MustAccAddressFromHex(streamRecord.Account), streamRecord.SettleTimestamp, settleTimestamp) - streamRecord.SettleTimestamp = settleTimestamp - return nil -} - -func (k Keeper) SettleStreamRecord(ctx sdk.Context, streamRecord *types.StreamRecord) error { - currentTimestamp := ctx.BlockTime().Unix() - crudTimestamp := streamRecord.CrudTimestamp - params := k.GetParams(ctx) - - if currentTimestamp != crudTimestamp { - if !streamRecord.NetflowRate.IsZero() { - flowDelta := streamRecord.NetflowRate.MulRaw(currentTimestamp - crudTimestamp) - fmt.Println("flowDelta", flowDelta.String()) - streamRecord.StaticBalance = streamRecord.StaticBalance.Add(flowDelta) - } - streamRecord.CrudTimestamp = currentTimestamp - } - - if streamRecord.StaticBalance.IsNegative() { - account := sdk.MustAccAddressFromHex(streamRecord.Account) - hasBankAccount := k.accountKeeper.HasAccount(ctx, account) - if hasBankAccount { - coins := sdk.NewCoins(sdk.NewCoin(params.FeeDenom, streamRecord.StaticBalance.Abs())) - err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, account, types.ModuleName, coins) - if err != nil { - ctx.Logger().Info("auto transfer failed when settling", "account", streamRecord.Account, "err", err, "coins", coins) - } else { - streamRecord.StaticBalance = sdkmath.ZeroInt() - } - } - } - - if streamRecord.NetflowRate.IsNegative() { - payDuration := streamRecord.StaticBalance.Add(streamRecord.BufferBalance).Quo(streamRecord.NetflowRate.Abs()) - if payDuration.LTE(sdkmath.NewIntFromUint64(params.ForcedSettleTime)) { err := k.ForceSettle(ctx, streamRecord) if err != nil { - ctx.Logger().Error("fail to force settle stream record", "err", err, "record", streamRecord.Account) - return err + return fmt.Errorf("check and force settle failed, err: %w", err) } - } else { - settleTimestamp := currentTimestamp - int64(params.ForcedSettleTime) + payDuration.Int64() - k.UpdateAutoSettleRecord(ctx, sdk.MustAccAddressFromHex(streamRecord.Account), streamRecord.SettleTimestamp, settleTimestamp) - streamRecord.SettleTimestamp = settleTimestamp } + settleTimestamp = currentTimestamp - int64(params.ForcedSettleTime) + payDuration.Int64() } - + k.UpdateAutoSettleRecord(ctx, sdk.MustAccAddressFromHex(streamRecord.Account), streamRecord.SettleTimestamp, settleTimestamp) + streamRecord.SettleTimestamp = settleTimestamp return nil } @@ -307,7 +264,7 @@ func (k Keeper) AutoSettle(ctx sdk.Context) { if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE { count++ // add one for a stream record - err := k.SettleStreamRecord(ctx, streamRecord) + err := k.UpdateStreamRecord(ctx, streamRecord, types.NewDefaultStreamRecordChangeWithAddr(addr)) if err != nil { ctx.Logger().Error("auto settle, settle stream record failed", "err", err.Error()) continue diff --git a/x/storage/keeper/payment.go b/x/storage/keeper/payment.go index 1fd0cfb60..42c4a5b50 100644 --- a/x/storage/keeper/payment.go +++ b/x/storage/keeper/payment.go @@ -166,19 +166,30 @@ func (k Keeper) IsPriceChanged(ctx sdk.Context, primarySpId uint32, priceTime in PriceTime: priceTime, }) if err != nil { - return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get storage price failed: %w", err) + return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get previous storage price failed: %w", err) } currentPrice, err := k.paymentKeeper.GetStoragePrice(ctx, types.StoragePriceParams{ PrimarySp: primarySpId, PriceTime: ctx.BlockTime().Unix(), }) if err != nil { - return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get storage price failed: %w", err) + return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get current storage price failed: %w", err) + } + + preParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, priceTime) + if err != nil { + return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get previous payment params failed: %w", err) + } + + currentParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, ctx.BlockTime().Unix()) + if err != nil { + return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get current payment params failed: %w", err) } return !(prePrice.ReadPrice.Equal(currentPrice.ReadPrice) && prePrice.PrimaryStorePrice.Equal(currentPrice.PrimaryStorePrice) && - prePrice.SecondaryStorePrice.Equal(currentPrice.SecondaryStorePrice)), + prePrice.SecondaryStorePrice.Equal(currentPrice.SecondaryStorePrice) && + preParams.ValidatorTaxRate == currentParams.ValidatorTaxRate), prePrice.ReadPrice, prePrice.PrimaryStorePrice, prePrice.SecondaryStorePrice, From c47444f09292699d22d3387c01b3081668b21967 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Thu, 20 Jul 2023 15:01:28 +0800 Subject: [PATCH 19/33] refactor codes --- e2e/tests/payment_test.go | 338 ++++++++++---------------------------- 1 file changed, 87 insertions(+), 251 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 80a1c7194..76fec33d6 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -43,10 +43,13 @@ type StreamRecords struct { type PaymentTestSuite struct { core.BaseSuite + defaultParams paymenttypes.Params } func (s *PaymentTestSuite) SetupSuite() { s.BaseSuite.SetupSuite() + s.defaultParams = s.queryParams() + } func (s *PaymentTestSuite) SetupTest() { @@ -95,31 +98,24 @@ func (s *PaymentTestSuite) TestCreatePaymentAccount() { // TestVersionedParams_SealAfterReserveTimeChange will cover the following case: // create an object, increase the reserve time, seal the object without error. func (s *PaymentTestSuite) TestVersionedParams_SealObjectAfterReserveTimeChange() { + defer s.revertParams() + ctx := context.Background() sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) // create bucket, create object user, bucketName, objectName, objectId, checksums := s.createBucketAndObject(sp) // update params - params := queryParamsResponse.GetParams() + params := s.queryParams() oldReserveTime := params.VersionedParams.ReserveTime oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) params.VersionedParams.ReserveTime = oldReserveTime * 2 params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) - s.updateParams(params) - queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params = queryParamsResponse.GetParams() - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) // seal object s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) @@ -139,24 +135,18 @@ func (s *PaymentTestSuite) TestVersionedParams_SealObjectAfterReserveTimeChange( // delete bucket msgDeleteBucket := storagetypes.NewMsgDeleteBucket(user.GetAddr(), bucketName) s.SendTxBlock(user, msgDeleteBucket) - - // revert params - params.VersionedParams.ReserveTime = oldReserveTime - params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate - s.updateParams(params) } // TestVersionedParams_DeleteAfterValidatorTaxRateChange will cover the following case: // create a bucket with non-zero read quota, change the validator tax rate, delete the bucket. // The rate of the validator tax address should be correct. func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRateChange() { + defer s.revertParams() + ctx := context.Background() sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) validatorTaxPoolRate := sdk.ZeroInt() queryStreamRequest := paymenttypes.QueryGetStreamRecordRequest{Account: paymenttypes.ValidatorTaxPoolAddress.String()} @@ -176,7 +166,7 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRate s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) // update params - params := queryParamsResponse.GetParams() + params := s.queryParams() oldReserveTime := params.VersionedParams.ReserveTime oldForceSettleTime := params.ForcedSettleTime oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate @@ -185,12 +175,7 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRate params.VersionedParams.ReserveTime = oldReserveTime / 2 params.ForcedSettleTime = oldForceSettleTime / 2 params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) - s.updateParams(params) - queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params = queryParamsResponse.GetParams() - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) // delete object msgDeleteObject := storagetypes.NewMsgDeleteObject(user.GetAddr(), bucketName, objectName) @@ -203,24 +188,17 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteBucketAfterValidatorTaxRate queryStreamResponse, err = s.Client.PaymentQueryClient.StreamRecord(ctx, &queryStreamRequest) s.Require().NoError(err) s.Require().Equal(validatorTaxPoolRate, queryStreamResponse.StreamRecord.NetflowRate) - - // revert params - params.VersionedParams.ReserveTime = oldReserveTime - params.ForcedSettleTime = oldForceSettleTime - params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate - s.updateParams(params) } // TestVersionedParams_DeleteObjectAfterReserveTimeChange will cover the following case: // create an object, change the reserve time, the object can be force deleted even the object's own has no enough balance. func (s *PaymentTestSuite) TestVersionedParams_DeleteObjectAfterReserveTimeChange() { + defer s.revertParams() + ctx := context.Background() sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) // create bucket, create object user, bucketName, objectName, objectId, checksums := s.createBucketAndObject(sp) @@ -253,19 +231,13 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteObjectAfterReserveTimeChang s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) // update params - params := queryParamsResponse.GetParams() + params := s.queryParams() oldReserveTime := params.VersionedParams.ReserveTime oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) params.VersionedParams.ReserveTime = oldReserveTime * 2 params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) - s.updateParams(params) - queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params = queryParamsResponse.GetParams() - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ BucketName: bucketName, @@ -295,11 +267,6 @@ func (s *PaymentTestSuite) TestVersionedParams_DeleteObjectAfterReserveTimeChang _, err = s.Client.HeadObject(ctx, &queryHeadObjectRequest) s.Require().ErrorContains(err, "No such object") - - // revert params - params.VersionedParams.ReserveTime = oldReserveTime - params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate - s.updateParams(params) } func (s *PaymentTestSuite) TestDeposit_ActiveAccount() { @@ -311,10 +278,8 @@ func (s *PaymentTestSuite) TestDeposit_ActiveAccount() { userAddr := user.GetAddr().String() var err error - params, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("params %s, err: %v", params, err) - s.Require().NoError(err) - reserveTime := params.Params.VersionedParams.ReserveTime + params := s.queryParams() + reserveTime := params.VersionedParams.ReserveTime queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ SpAddr: sp.OperatorKey.GetAddr().String(), }) @@ -324,7 +289,7 @@ func (s *PaymentTestSuite) TestDeposit_ActiveAccount() { bucketChargedReadQuota := uint64(1000) readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice totalUserRate := readPrice.MulInt(sdkmath.NewIntFromUint64(bucketChargedReadQuota)).TruncateInt() - taxRateParam := params.Params.VersionedParams.ValidatorTaxRate + taxRateParam := params.VersionedParams.ValidatorTaxRate taxStreamRate := taxRateParam.MulInt(totalUserRate).TruncateInt() expectedRate := totalUserRate.Add(taxStreamRate) paymentAccountBNBNeeded := expectedRate.Mul(sdkmath.NewIntFromUint64(reserveTime)) @@ -399,10 +364,8 @@ func (s *PaymentTestSuite) TestDeposit_ResumeInOneBlock() { userAddr := user.GetAddr().String() var err error - params, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("params %s, err: %v", params, err) - s.Require().NoError(err) - reserveTime := params.Params.VersionedParams.ReserveTime + params := s.queryParams() + reserveTime := params.VersionedParams.ReserveTime queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ SpAddr: sp.OperatorKey.GetAddr().String(), }) @@ -412,7 +375,7 @@ func (s *PaymentTestSuite) TestDeposit_ResumeInOneBlock() { bucketChargedReadQuota := uint64(1000) readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice totalUserRate := readPrice.MulInt(sdkmath.NewIntFromUint64(bucketChargedReadQuota)).TruncateInt() - taxRateParam := params.Params.VersionedParams.ValidatorTaxRate + taxRateParam := params.VersionedParams.ValidatorTaxRate taxStreamRate := taxRateParam.MulInt(totalUserRate).TruncateInt() expectedRate := totalUserRate.Add(taxStreamRate) paymentAccountBNBNeeded := expectedRate.Mul(sdkmath.NewIntFromUint64(reserveTime)) @@ -505,21 +468,13 @@ func (s *PaymentTestSuite) TestDeposit_ResumeInOneBlock() { } func (s *PaymentTestSuite) TestDeposit_ResumeInBlocks() { + defer s.revertParams() + ctx := context.Background() // update params - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params := queryParamsResponse.GetParams() - oldMaxAutoResumeFlowCount := params.MaxAutoResumeFlowCount - s.T().Logf("params, MaxAutoResumeFlowCount: %d", oldMaxAutoResumeFlowCount) - + params := s.queryParams() params.MaxAutoResumeFlowCount = 1 // update to 1 s.updateParams(params) - queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params = queryParamsResponse.GetParams() - s.T().Logf("params: %s", params.String()) sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() @@ -645,10 +600,6 @@ func (s *PaymentTestSuite) TestDeposit_ResumeInBlocks() { s.T().Fatalf("wait for resume time timeout") } } - - // revert params - params.MaxAutoResumeFlowCount = oldMaxAutoResumeFlowCount - s.updateParams(params) } func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { @@ -667,10 +618,8 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { family := queryFamilyResponse.GlobalVirtualGroupFamily bucketChargedReadQuota := uint64(1000) - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) - reserveTime := paymentParams.Params.VersionedParams.ReserveTime + params := s.queryParams() + reserveTime := params.VersionedParams.ReserveTime queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ SpAddr: sp.OperatorKey.GetAddr().String(), }) @@ -678,7 +627,7 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { s.Require().NoError(err) readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice totalUserRate := readPrice.MulInt(sdkmath.NewIntFromUint64(bucketChargedReadQuota)).TruncateInt() - taxRateParam := paymentParams.Params.VersionedParams.ValidatorTaxRate + taxRateParam := params.VersionedParams.ValidatorTaxRate taxStreamRate := taxRateParam.MulInt(totalUserRate).TruncateInt() expectedRate := totalUserRate.Add(taxStreamRate) paymentAccountBNBNeeded := expectedRate.Mul(sdkmath.NewIntFromUint64(reserveTime)) @@ -793,21 +742,13 @@ func (s *PaymentTestSuite) TestAutoSettle_InOneBlock() { } func (s *PaymentTestSuite) TestAutoSettle_InBlocks() { + defer s.revertParams() + ctx := context.Background() // update params - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params := queryParamsResponse.GetParams() - oldMaxAutoSettleFlowCount := params.MaxAutoSettleFlowCount - s.T().Logf("params, MaxAutoSettleFlowCount: %d", oldMaxAutoSettleFlowCount) - + params := s.queryParams() params.MaxAutoSettleFlowCount = 2 // update to 2 s.updateParams(params) - queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params = queryParamsResponse.GetParams() - s.T().Logf("params: %s", params.String()) sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() @@ -899,10 +840,6 @@ func (s *PaymentTestSuite) TestAutoSettle_InBlocks() { paymentStreamRecordAfterAutoSettle := s.getStreamRecord(paymentAddr) s.T().Logf("paymentStreamRecordAfterAutoSettle %s", core.YamlString(paymentStreamRecordAfterAutoSettle)) s.Require().NotEqual(paymentStreamRecordAfterAutoSettle.Status, paymenttypes.STREAM_ACCOUNT_STATUS_ACTIVE) - - // revert params - params.MaxAutoSettleFlowCount = oldMaxAutoSettleFlowCount - s.updateParams(params) } func (s *PaymentTestSuite) TestWithdraw() { @@ -914,10 +851,8 @@ func (s *PaymentTestSuite) TestWithdraw() { userAddr := user.GetAddr().String() var err error - params, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("params %s, err: %v", params, err) - s.Require().NoError(err) - reserveTime := params.Params.VersionedParams.ReserveTime + params := s.queryParams() + reserveTime := params.VersionedParams.ReserveTime queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ SpAddr: sp.OperatorKey.GetAddr().String(), }) @@ -927,7 +862,7 @@ func (s *PaymentTestSuite) TestWithdraw() { bucketChargedReadQuota := uint64(100000) readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice totalUserRate := readPrice.MulInt(sdkmath.NewIntFromUint64(bucketChargedReadQuota)).TruncateInt() - taxRateParam := params.Params.VersionedParams.ValidatorTaxRate + taxRateParam := params.VersionedParams.ValidatorTaxRate taxStreamRate := taxRateParam.MulInt(totalUserRate).TruncateInt() expectedRate := totalUserRate.Add(taxStreamRate) paymentAccountBNBNeeded := expectedRate.Mul(sdkmath.NewIntFromUint64(reserveTime)) @@ -1060,9 +995,7 @@ func (s *PaymentTestSuite) TestStorageBill_Smoke() { streamRecordsBeforeCreateBucket := s.getStreamRecords(streamAddresses) s.T().Logf("streamRecordsBeforeCreateBucket: %s", core.YamlString(streamRecordsBeforeCreateBucket)) - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) + params := s.queryParams() // create bucket bucketName := storagetestutils.GenRandomBucketName() @@ -1105,7 +1038,7 @@ func (s *PaymentTestSuite) TestStorageBill_Smoke() { readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice readChargeRate := readPrice.MulInt(sdk.NewIntFromUint64(queryHeadBucketResponse.BucketInfo.ChargedReadQuota)).TruncateInt() s.T().Logf("readPrice: %s, readChargeRate: %s", readPrice, readChargeRate) - userTaxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() + userTaxRate := params.VersionedParams.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() userTotalRate := readChargeRate.Add(userTaxRate) s.Require().Equal(userStreamRecord.NetflowRate.Abs(), userTotalRate) expectedOutFlows := []paymenttypes.OutFlow{ @@ -1173,8 +1106,8 @@ func (s *PaymentTestSuite) TestStorageBill_Smoke() { secondaryStorePrice := queryGetSecondarySpStorePriceByTime.SecondarySpStorePrice.StorePrice chargeSize := s.getChargeSize(queryHeadObjectResponse.ObjectInfo.PayloadSize) expectedChargeRate := primaryStorePrice.Add(secondaryStorePrice.MulInt64(6)).MulInt(sdk.NewIntFromUint64(chargeSize)).TruncateInt() - expectedChargeRate = paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(expectedChargeRate).TruncateInt().Add(expectedChargeRate) - expectedLockedBalance := expectedChargeRate.Mul(sdkmath.NewIntFromUint64(paymentParams.Params.VersionedParams.ReserveTime)) + expectedChargeRate = params.VersionedParams.ValidatorTaxRate.MulInt(expectedChargeRate).TruncateInt().Add(expectedChargeRate) + expectedLockedBalance := expectedChargeRate.Mul(sdkmath.NewIntFromUint64(params.VersionedParams.ReserveTime)) streamRecordsAfterCreateObject := s.getStreamRecords(streamAddresses) s.T().Logf("streamRecordsAfterCreateObject %s", core.YamlString(streamRecordsAfterCreateObject)) @@ -1452,6 +1385,8 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChange() } func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChangeReserveTimeChange() { + defer s.revertParams() + var err error ctx := context.Background() sp := s.PickStorageProvider() @@ -1544,22 +1479,13 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChangeRes s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) // update params - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params := queryParamsResponse.GetParams() + params := s.queryParams() oldReserveTime := params.VersionedParams.ReserveTime oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) params.VersionedParams.ReserveTime = oldReserveTime * 2 params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) - s.updateParams(params) - queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params = queryParamsResponse.GetParams() - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) s.SendTxBlock(user, msgDeleteObject) s.SendTxBlock(user, msgDeleteBucket) @@ -1580,12 +1506,6 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObjectBucket_WithPriceChangeRes StorePrice: priceRes.SpStoragePrice.StorePrice, } s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) - - // revert params - params = queryParamsResponse.Params - params.VersionedParams.ReserveTime = oldReserveTime - params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate - s.updateParams(params) } func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreLessThanReserveTime() { @@ -1601,11 +1521,8 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreLessThanReserve family := queryFamilyResponse.GlobalVirtualGroupFamily user := s.GenAndChargeAccounts(1, 1000000)[0] - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - s.T().Log("queryParamsResponse", core.YamlString(queryParamsResponse)) - reserveTime := queryParamsResponse.Params.VersionedParams.ReserveTime + params := s.queryParams() + reserveTime := params.VersionedParams.ReserveTime // create bucket bucketName := s.createBucket(sp, user, 256) @@ -1654,6 +1571,8 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreLessThanReserve } func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreMoreThanReserveTime() { + defer s.revertParams() + var err error ctx := context.Background() sp := s.PickStorageProvider() @@ -1666,14 +1585,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreMoreThanReserve family := queryFamilyResponse.GlobalVirtualGroupFamily user := s.GenAndChargeAccounts(1, 1000000)[0] - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - s.T().Log("queryParamsResponse", core.YamlString(queryParamsResponse)) - oldReserveTime := queryParamsResponse.Params.VersionedParams.ReserveTime - oldForceSettleTime := queryParamsResponse.Params.ForcedSettleTime - - params := queryParamsResponse.Params + params := s.queryParams() params.VersionedParams.ReserveTime = 5 params.ForcedSettleTime = 2 s.updateParams(params) @@ -1739,12 +1651,6 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreMoreThanReserve taxPoolDelta := streamRecordsAfter.Tax.StaticBalance.Sub(streamRecordsBefore.Tax.StaticBalance) s.T().Log("familyDelta", familyDelta, "gvgDelta", gvgDelta, "taxPoolDelta", taxPoolDelta) s.Require().True(familyDelta.Add(gvgDelta).Add(taxPoolDelta).Int64() >= balanceDelta.Int64()) // could exist other buckets/objects on the gvg & family - - // revert params - params = queryParamsResponse.Params - params.VersionedParams.ReserveTime = oldReserveTime - params.ForcedSettleTime = oldForceSettleTime - s.updateParams(params) } func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuota() { @@ -1768,9 +1674,7 @@ func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuot } streamRecordsBefore := s.getStreamRecords(streamAddresses) - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) + params := s.queryParams() // case: create bucket with zero read quota bucketName := s.createBucket(sp, user, 0) @@ -1810,7 +1714,7 @@ func (s *PaymentTestSuite) TestStorageBill_CreateBucket_WithZeroNoneZeroReadQuot readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice readChargeRate := readPrice.MulInt(sdk.NewIntFromUint64(queryHeadBucketResponse.BucketInfo.ChargedReadQuota)).TruncateInt() s.T().Logf("readPrice: %s, readChargeRate: %s", readPrice, readChargeRate) - taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() + taxRate := params.VersionedParams.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() userTotalRate := readChargeRate.Add(taxRate) // assertions @@ -1855,10 +1759,6 @@ func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithZeroNoneZeroPayload( paymenttypes.ValidatorTaxPoolAddress.String(), } - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) - bucketName := s.createBucket(sp, user, 0) // case: create object with zero payload size @@ -1891,6 +1791,8 @@ func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithZeroNoneZeroPayload( } func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithReserveTimeValidatorTaxRateChange() { + defer s.revertParams() + var err error ctx := context.Background() sp := s.PickStorageProvider() @@ -1910,10 +1812,6 @@ func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithReserveTimeValidator paymenttypes.ValidatorTaxPoolAddress.String(), } - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) - bucketName := s.createBucket(sp, user, 0) // create object with none zero payload size @@ -1931,22 +1829,14 @@ func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithReserveTimeValidator s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) // update params - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params := queryParamsResponse.GetParams() + + params := s.queryParams() oldReserveTime := params.VersionedParams.ReserveTime oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) params.VersionedParams.ReserveTime = oldReserveTime * 2 params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) - s.updateParams(params) - queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params = queryParamsResponse.GetParams() - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) // create another object after parameter changes streamRecordsBefore = s.getStreamRecords(streamAddresses) @@ -1962,11 +1852,6 @@ func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithReserveTimeValidator s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) s.Require().True(lockFeeAfterParameterChange.GT(lockFee.MulRaw(2))) - - // revert params - params.VersionedParams.ReserveTime = oldReserveTime - params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate - s.updateParams(params) } func (s *PaymentTestSuite) TestStorageBill_CancelCreateObject() { @@ -1989,10 +1874,6 @@ func (s *PaymentTestSuite) TestStorageBill_CancelCreateObject() { paymenttypes.ValidatorTaxPoolAddress.String(), } - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) - bucketName := s.createBucket(sp, user, 0) // create object with none zero payload size @@ -2042,10 +1923,6 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithoutPriceChange() { paymenttypes.ValidatorTaxPoolAddress.String(), } - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) - bucketName := s.createBucket(sp, user, 0) // create object with none zero payload size @@ -2096,10 +1973,6 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChange() { paymenttypes.ValidatorTaxPoolAddress.String(), } - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) - bucketName := s.createBucket(sp, user, 102400) // case: seal object with read price change and storage price change @@ -2140,6 +2013,8 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChange() { } func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChangeValidatorTaxRateChange() { + defer s.revertParams() + var err error ctx := context.Background() sp := s.PickStorageProvider() @@ -2159,10 +2034,6 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChangeValidatorTa paymenttypes.ValidatorTaxPoolAddress.String(), } - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) - bucketName := s.createBucket(sp, user, 102400) // case: seal object with read price change and storage price change @@ -2202,22 +2073,13 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChangeValidatorTa s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRateReadAfter.Sub(taxRateReadBefore).Add(taxRateStore)) // update params - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params := queryParamsResponse.GetParams() + params := s.queryParams() oldReserveTime := params.VersionedParams.ReserveTime oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) params.VersionedParams.ReserveTime = oldReserveTime * 2 params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) - s.updateParams(params) - queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params = queryParamsResponse.GetParams() - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) _, _, objectName, objectId, checksums, payloadSize = s.createObject(user, bucketName, false) s.sealObject(sp, gvg, bucketName, objectName, objectId, checksums) @@ -2239,11 +2101,6 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChangeValidatorTa s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRateStore) s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRateReadAfter.Sub(gvgFamilyRateReadBefore).Add(gvgFamilyRateStore)) s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRateReadAfter.Sub(taxRateReadBefore).Add(taxRateStore)) - - // revert params - params.VersionedParams.ReserveTime = oldReserveTime - params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate - s.updateParams(params) } func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { @@ -2888,6 +2745,8 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChange() { } func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeChange() { + defer s.revertParams() + ctx := context.Background() sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() @@ -2976,22 +2835,13 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh s.Require().Equal(int64(0), queryBalanceResponse.Balance.Amount.Int64()) // update params - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params := queryParamsResponse.GetParams() + params := s.queryParams() oldReserveTime := params.VersionedParams.ReserveTime oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", oldReserveTime, oldValidatorTaxRate) params.VersionedParams.ReserveTime = oldReserveTime * 2 params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) - s.updateParams(params) - queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params = queryParamsResponse.GetParams() - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) // for payment time.Sleep(2 * time.Second) @@ -3039,14 +2889,11 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh StorePrice: priceRes.SpStoragePrice.StorePrice, } s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) - - // revert params - params.VersionedParams.ReserveTime = oldReserveTime - params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate - s.updateParams(params) } func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeChange_FrozenAccount() { + defer s.revertParams() + ctx := context.Background() sp := s.PickStorageProvider() gvg, found := sp.GetFirstGlobalVirtualGroup() @@ -3059,14 +2906,9 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh user := s.GenAndChargeAccounts(1, 1000000)[0] // params - queryParamsRequest := paymenttypes.QueryParamsRequest{} - queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params := queryParamsResponse.GetParams() + params := s.queryParams() oldReserveTime := params.VersionedParams.ReserveTime - oldForceSettleTime := params.ForcedSettleTime oldValidatorTaxRate := params.VersionedParams.ValidatorTaxRate - s.T().Log("params", core.YamlString(params)) streamAddresses := []string{ user.GetAddr().String(), @@ -3157,12 +2999,7 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh // update params params.VersionedParams.ReserveTime = oldReserveTime * 2 params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate.MulInt64(2) - s.updateParams(params) - queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) - s.Require().NoError(err) - params = queryParamsResponse.GetParams() - s.T().Logf("params, ReserveTime: %d, ValidatorTaxRate: %s", params.VersionedParams.ReserveTime, params.VersionedParams.ValidatorTaxRate) // for payment time.Sleep(2 * time.Second) @@ -3210,12 +3047,6 @@ func (s *PaymentTestSuite) TestDiscontinue_InBlocks_WithPriceChangeReserveTimeCh StorePrice: priceRes.SpStoragePrice.StorePrice, } s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) - - // revert params - params.VersionedParams.ReserveTime = oldReserveTime - params.ForcedSettleTime = oldForceSettleTime - params.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate - s.updateParams(params) } func TestPaymentTestSuite(t *testing.T) { @@ -3288,9 +3119,7 @@ func (s *PaymentTestSuite) getChargeSize(payloadSize uint64) uint64 { func (s *PaymentTestSuite) calculateLockFee(sp *core.StorageProvider, bucketName, objectName string, payloadSize uint64) sdkmath.Int { ctx := context.Background() - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) + params := s.queryParams() headBucketExtraResponse, err := s.Client.HeadBucketExtra(ctx, &storagetypes.QueryHeadBucketExtraRequest{BucketName: bucketName}) s.Require().NoError(err) @@ -3305,8 +3134,8 @@ func (s *PaymentTestSuite) calculateLockFee(sp *core.StorageProvider, bucketName gvgFamilyRate := primaryPrice.MulInt64(chargeSize).TruncateInt() gvgRate := secondaryPrice.MulInt64(chargeSize * int64(secondarySpCount)).TruncateInt() - taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() - return gvgFamilyRate.Add(gvgRate).Add(taxRate).MulRaw(int64(paymentParams.Params.VersionedParams.ReserveTime)) + taxRate := params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() + return gvgFamilyRate.Add(gvgRate).Add(taxRate).MulRaw(int64(params.VersionedParams.ReserveTime)) } func (s *PaymentTestSuite) getPrices(sp *core.StorageProvider, timestamp int64) (sdk.Dec, sdk.Dec, sdk.Dec) { @@ -3332,9 +3161,7 @@ func (s *PaymentTestSuite) getPrices(sp *core.StorageProvider, timestamp int64) func (s *PaymentTestSuite) calculateReadRates(sp *core.StorageProvider, bucketName string) (sdkmath.Int, sdkmath.Int, sdkmath.Int) { ctx := context.Background() - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) + params := s.queryParams() headBucketRequest := storagetypes.QueryHeadBucketRequest{ BucketName: bucketName, @@ -3345,16 +3172,14 @@ func (s *PaymentTestSuite) calculateReadRates(sp *core.StorageProvider, bucketNa readPrice, _, _ := s.getPrices(sp, headBucketResponse.BucketInfo.CreateAt) gvgFamilyRate := readPrice.MulInt64(int64(headBucketResponse.BucketInfo.ChargedReadQuota)).TruncateInt() - taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate).TruncateInt() + taxRate := params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate).TruncateInt() return gvgFamilyRate, taxRate, gvgFamilyRate.Add(taxRate) } func (s *PaymentTestSuite) calculateReadRatesCurrentTimestamp(sp *core.StorageProvider, bucketName string) (sdkmath.Int, sdkmath.Int, sdkmath.Int) { ctx := context.Background() - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) + params := s.queryParams() headBucketRequest := storagetypes.QueryHeadBucketRequest{ BucketName: bucketName, @@ -3365,16 +3190,14 @@ func (s *PaymentTestSuite) calculateReadRatesCurrentTimestamp(sp *core.StoragePr readPrice, _, _ := s.getPrices(sp, time.Now().Unix()) gvgFamilyRate := readPrice.MulInt64(int64(headBucketResponse.BucketInfo.ChargedReadQuota)).TruncateInt() - taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate).TruncateInt() + taxRate := params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate).TruncateInt() return gvgFamilyRate, taxRate, gvgFamilyRate.Add(taxRate) } func (s *PaymentTestSuite) calculateStorageRates(sp *core.StorageProvider, bucketName, objectName string, payloadSize uint64) (sdkmath.Int, sdkmath.Int, sdkmath.Int, sdkmath.Int) { ctx := context.Background() - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) + params := s.queryParams() queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ BucketName: bucketName, @@ -3396,16 +3219,12 @@ func (s *PaymentTestSuite) calculateStorageRates(sp *core.StorageProvider, bucke gvgFamilyRate := primaryPrice.MulInt64(chargeSize).TruncateInt() gvgRate := secondaryPrice.MulInt64(chargeSize * int64(gvgCount)).TruncateInt() - taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() + taxRate := params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() return gvgFamilyRate, gvgRate, taxRate, gvgFamilyRate.Add(gvgRate).Add(taxRate) } func (s *PaymentTestSuite) calculateStorageRatesCurrentTimestamp(sp *core.StorageProvider, bucketName, objectName string, payloadSize uint64) (sdkmath.Int, sdkmath.Int, sdkmath.Int, sdkmath.Int) { - ctx := context.Background() - - paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) - s.T().Logf("paymentParams %s, err: %v", paymentParams, err) - s.Require().NoError(err) + params := s.queryParams() queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ BucketName: bucketName, @@ -3420,7 +3239,7 @@ func (s *PaymentTestSuite) calculateStorageRatesCurrentTimestamp(sp *core.Storag gvgFamilyRate := primaryPrice.MulInt64(chargeSize).TruncateInt() gvgRate := secondaryPrice.MulInt64(chargeSize * int64(gvgCount)).TruncateInt() - taxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() + taxRate := params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() return gvgFamilyRate, gvgRate, taxRate, gvgFamilyRate.Add(gvgRate).Add(taxRate) } @@ -3434,7 +3253,7 @@ func (s *PaymentTestSuite) updateParams(params paymenttypes.Params) { queryParamsRequest := &paymenttypes.QueryParamsRequest{} queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, queryParamsRequest) s.Require().NoError(err) - s.T().Log("queryParamsResponse", core.YamlString(queryParamsResponse.Params)) + s.T().Log("params before", core.YamlString(queryParamsResponse.Params)) msgUpdateParams := &paymenttypes.MsgUpdateParams{ Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), @@ -3492,9 +3311,14 @@ func (s *PaymentTestSuite) updateParams(params paymenttypes.Params) { queryParamsByTimestampRequest := &paymenttypes.QueryParamsByTimestampRequest{Timestamp: ts} queryParamsByTimestampResponse, err := s.Client.PaymentQueryClient.ParamsByTimestamp(ctx, queryParamsByTimestampRequest) s.Require().NoError(err) - s.T().Log("queryParamsByTimestampResponse", core.YamlString(queryParamsResponse.Params)) + s.T().Log("params by timestamp", core.YamlString(queryParamsResponse.Params)) s.Require().Equal(queryParamsResponse.Params.VersionedParams.ReserveTime, queryParamsByTimestampResponse.Params.VersionedParams.ReserveTime) + + queryParamsRequest = &paymenttypes.QueryParamsRequest{} + queryParamsResponse, err = s.Client.PaymentQueryClient.Params(ctx, queryParamsRequest) + s.Require().NoError(err) + s.T().Log("params after", core.YamlString(queryParamsResponse.Params)) } func (s *PaymentTestSuite) createBucketAndObject(sp *core.StorageProvider) (keys.KeyManager, string, string, storagetypes.Uint, [][]byte) { @@ -3792,3 +3616,15 @@ CheckProposalStatus: s.T().Errorf("update params failed") } } + +func (s *PaymentTestSuite) revertParams() { + s.updateParams(s.defaultParams) +} + +func (s *PaymentTestSuite) queryParams() paymenttypes.Params { + queryParamsRequest := paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(context.Background(), &queryParamsRequest) + s.Require().NoError(err) + s.T().Log("params", core.YamlString(queryParamsResponse.Params)) + return queryParamsResponse.Params +} From 3240d42ee6eb70f79586eacd383cd0525c2a6e59 Mon Sep 17 00:00:00 2001 From: Fynn Date: Thu, 20 Jul 2023 15:19:14 +0800 Subject: [PATCH 20/33] fix get stat of sp panic --- x/virtualgroup/keeper/keeper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/virtualgroup/keeper/keeper.go b/x/virtualgroup/keeper/keeper.go index 7033af62b..9e8fbf81d 100644 --- a/x/virtualgroup/keeper/keeper.go +++ b/x/virtualgroup/keeper/keeper.go @@ -126,7 +126,7 @@ func (k Keeper) DeleteGVG(ctx sdk.Context, primarySp *sptypes.StorageProvider, g gvgFamily.MustRemoveGVG(gvg.Id) // update stat - stat := k.MustGetGVGStatisticsWithinSP(ctx, gvgFamily.Id) + stat := k.MustGetGVGStatisticsWithinSP(ctx, gvgFamily.PrimarySpId) stat.PrimaryCount-- k.SetGVGStatisticsWithSP(ctx, stat) From bb328f12be0d65b030abe9bc632275f76d79aabd Mon Sep 17 00:00:00 2001 From: Fynn Date: Thu, 20 Jul 2023 16:15:42 +0800 Subject: [PATCH 21/33] fix vg test --- e2e/tests/virtualgroup_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/e2e/tests/virtualgroup_test.go b/e2e/tests/virtualgroup_test.go index 2a724af05..91afee122 100644 --- a/e2e/tests/virtualgroup_test.go +++ b/e2e/tests/virtualgroup_test.go @@ -381,7 +381,13 @@ func (s *VirtualGroupTestSuite) TestSPExit() { s.BaseSuite.CreateObject(user, sp, gvgID, storagetestutil.GenRandomBucketName(), storagetestutil.GenRandomObjectName()) // 4. Create another gvg contains this new sp - anotherSP := s.StorageProviders[1] + var anotherSP *core.StorageProvider + for _, tsp := range s.StorageProviders { + if tsp.Info.Id != sp.Info.Id && tsp.Info.Id != successorSp.Info.Id { + anotherSP = tsp + break + } + } var anotherSecondarySPIDs []uint32 for _, ssp := range s.StorageProviders { if ssp.Info.Id != successorSp.Info.Id && ssp.Info.Id != anotherSP.Info.Id { From ebc183c77d9ff78ffeff854c902098d51ded608d Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Thu, 20 Jul 2023 16:28:58 +0800 Subject: [PATCH 22/33] fix an issue --- e2e/tests/payment_test.go | 77 ++++++++++++++++++++- e2e/tests/storage_bill_test.go | 8 ++- x/payment/keeper/storage_fee_charge_test.go | 1 + x/payment/keeper/stream_record.go | 24 +++---- 4 files changed, 93 insertions(+), 17 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 76fec33d6..3a489e0b0 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -2103,7 +2103,9 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithPriceChangeValidatorTa s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRateReadAfter.Sub(taxRateReadBefore).Add(taxRateStore)) } -func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { +func (s *PaymentTestSuite) TestStorageBill_FullLifecycle() { + defer s.revertParams() + var err error ctx := context.Background() sp := s.PickStorageProvider() @@ -2116,6 +2118,14 @@ func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { family := queryFamilyResponse.GlobalVirtualGroupFamily user := s.GenAndChargeAccounts(1, 1000000)[0] + // query storage price + priceRes, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ + SpAddr: sp.OperatorKey.GetAddr().String(), + Timestamp: 0, + }) + s.Require().NoError(err) + s.T().Log("price", priceRes.SpStoragePrice) + streamAddresses := []string{ user.GetAddr().String(), family.VirtualPaymentAddress, @@ -2133,13 +2143,60 @@ func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { bucketName2 := s.createBucket(sp, user, 1024) _, _, objectName3, objectId3, checksums3, _ := s.createObject(user, bucketName2, false) s.sealObject(sp, gvg, bucketName2, objectName3, objectId3, checksums3) + + // update params + params := s.queryParams() + params.VersionedParams.ReserveTime = params.VersionedParams.ReserveTime * 3 + params.ForcedSettleTime = params.ForcedSettleTime * 2 + s.updateParams(params) + _, _, objectName4, objectId4, checksums4, _ := s.createObject(user, bucketName2, false) s.sealObject(sp, gvg, bucketName2, objectName4, objectId4, checksums4) + bucketName3 := s.createBucket(sp, user, 1024) + _, _, objectName5, objectId5, checksums5, _ := s.createObject(user, bucketName3, false) + s.sealObject(sp, gvg, bucketName3, objectName5, objectId5, checksums5) + + // update new price + msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice.MulInt64(10000), + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) + + // update params + params = s.queryParams() + params.VersionedParams.ReserveTime = params.VersionedParams.ReserveTime / 2 + params.ForcedSettleTime = params.ForcedSettleTime / 3 + s.updateParams(params) + + _, _, objectName6, objectId6, checksums6, _ := s.createObject(user, bucketName3, false) + s.sealObject(sp, gvg, bucketName3, objectName6, objectId6, checksums6) + + bucketName4 := s.createBucket(sp, user, 1024) + _, _, objectName7, objectId7, checksums7, _ := s.createObject(user, bucketName4, false) + s.sealObject(sp, gvg, bucketName4, objectName7, objectId7, checksums7) + + // update params + params = s.queryParams() + params.VersionedParams.ValidatorTaxRate = params.VersionedParams.ValidatorTaxRate.MulInt64(2) + s.updateParams(params) + + _, _, objectName8, objectId8, checksums8, _ := s.createObject(user, bucketName4, false) + s.sealObject(sp, gvg, bucketName4, objectName8, objectId8, checksums8) + time.Sleep(3 * time.Second) _ = s.deleteObject(user, bucketName1, objectName1) _ = s.deleteObject(user, bucketName1, objectName2) + + // update params + params = s.queryParams() + params.VersionedParams.ValidatorTaxRate = params.VersionedParams.ValidatorTaxRate.MulInt64(3) + s.updateParams(params) + _ = s.deleteObject(user, bucketName2, objectName3) _ = s.deleteObject(user, bucketName2, objectName4) err = s.deleteBucket(user, bucketName1) @@ -2147,6 +2204,15 @@ func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { err = s.deleteBucket(user, bucketName2) s.Require().Error(err) + _ = s.deleteObject(user, bucketName3, objectName5) + _ = s.deleteObject(user, bucketName3, objectName6) + _ = s.deleteObject(user, bucketName4, objectName7) + _ = s.deleteObject(user, bucketName4, objectName8) + err = s.deleteBucket(user, bucketName3) + s.Require().Error(err) + err = s.deleteBucket(user, bucketName4) + s.Require().Error(err) + // assertions streamRecordsAfter := s.getStreamRecords(streamAddresses) s.Require().True(!streamRecordsAfter.User.StaticBalance.IsZero()) @@ -2154,6 +2220,15 @@ func (s *PaymentTestSuite) TestStorageBill_FullLifecycle_WithEnoughBalance() { s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // revert price + msgUpdatePrice = &sptypes.MsgUpdateSpStoragePrice{ + SpAddress: sp.OperatorKey.GetAddr().String(), + ReadPrice: priceRes.SpStoragePrice.ReadPrice, + FreeReadQuota: priceRes.SpStoragePrice.FreeReadQuota, + StorePrice: priceRes.SpStoragePrice.StorePrice, + } + s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) } func (s *PaymentTestSuite) TestVirtualGroup_Settle() { diff --git a/e2e/tests/storage_bill_test.go b/e2e/tests/storage_bill_test.go index a3680e890..14d41836e 100644 --- a/e2e/tests/storage_bill_test.go +++ b/e2e/tests/storage_bill_test.go @@ -182,6 +182,7 @@ func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithPriceChange() { SpAddr: sp.OperatorKey.GetAddr().String(), Timestamp: 0, }) + s.Require().NoError(err) // update new price msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ SpAddress: sp.OperatorKey.GetAddr().String(), @@ -372,7 +373,7 @@ func (s *PaymentTestSuite) TestStorageBill_UpdatePaymentAddress() { user := s.GenAndChargeAccounts(1, 100)[0] paymentAccountAddr := s.CreatePaymentAccount(user, 1, 17) - paymentAcc, err := sdk.AccAddressFromHexUnsafe(paymentAccountAddr) + paymentAcc := sdk.MustAccAddressFromHex(paymentAccountAddr) streamAddresses := []string{ user.GetAddr().String(), family.VirtualPaymentAddress, @@ -505,7 +506,7 @@ func (s *PaymentTestSuite) TestStorageBill_UpdatePaymentAddress() { s.SendTxBlockWithExpectErrorString(msgUpdateBucketInfo, user, "apply user flows list failed") // new payment account balance not enough paymentAccountAddr = s.CreatePaymentAccount(user, 1, 13) - paymentAcc, err = sdk.AccAddressFromHexUnsafe(paymentAccountAddr) + paymentAcc = sdk.MustAccAddressFromHex(paymentAccountAddr) msgUpdateBucketInfo = storagetypes.NewMsgUpdateBucketInfo( user.GetAddr(), bucketName, &readQuota, paymentAcc, storagetypes.VISIBILITY_TYPE_PRIVATE) @@ -534,6 +535,7 @@ func (s *PaymentTestSuite) RecoverSPPrice(sp *core.StorageProvider) { SpAddr: sp.OperatorKey.GetAddr().String(), Timestamp: time.Now().Unix(), }) + s.Require().NoError(err) s.T().Logf("queryGetSpStoragePriceByTimeResp read price: %s", queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice) } @@ -554,7 +556,7 @@ func (s *PaymentTestSuite) CreatePaymentAccount(user keys.KeyManager, amount, de s.T().Log(paymentAccounts) paymentAccountAddr := paymentAccounts.PaymentAccounts[len(paymentAccounts.PaymentAccounts)-1] // charge payment account - paymentAcc, err := sdk.AccAddressFromHexUnsafe(paymentAccountAddr) + paymentAcc := sdk.MustAccAddressFromHex(paymentAccountAddr) msgSend := banktypes.NewMsgSend(user.GetAddr(), paymentAcc, []sdk.Coin{{Denom: "BNB", Amount: types.NewIntFromInt64WithDecimal(amount, decimal)}}) s.SendTxBlock(user, msgSend) diff --git a/x/payment/keeper/storage_fee_charge_test.go b/x/payment/keeper/storage_fee_charge_test.go index 7c3df2079..7faf16db7 100644 --- a/x/payment/keeper/storage_fee_charge_test.go +++ b/x/payment/keeper/storage_fee_charge_test.go @@ -184,6 +184,7 @@ func TestAutoForceSettle(t *testing.T) { usrBeforeForceSettle, _ := keeper.GetStreamRecord(ctx, user) t.Logf("usrBeforeForceSettle: %s", usrBeforeForceSettle) + ctx = ctx.WithValue(types.ForceUpdateStreamRecordKey, true) time.Sleep(1 * time.Second) keeper.AutoSettle(ctx) diff --git a/x/payment/keeper/stream_record.go b/x/payment/keeper/stream_record.go index 42efce7f3..a965f44e9 100644 --- a/x/payment/keeper/stream_record.go +++ b/x/payment/keeper/stream_record.go @@ -3,11 +3,10 @@ package keeper import ( "fmt" - "github.com/cosmos/cosmos-sdk/telemetry" - sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/store/prefix" storetypes "github.com/cosmos/cosmos-sdk/store/types" + "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/bnb-chain/greenfield/x/payment/types" @@ -155,16 +154,15 @@ func (k Keeper) UpdateStreamRecord(ctx sdk.Context, streamRecord *types.StreamRe } } // update buffer balance - if !change.RateChange.IsZero() { - streamRecord.NetflowRate = streamRecord.NetflowRate.Add(change.RateChange) - newBufferBalance := sdkmath.ZeroInt() - if streamRecord.NetflowRate.IsNegative() { - newBufferBalance = streamRecord.NetflowRate.Abs().Mul(sdkmath.NewIntFromUint64(params.VersionedParams.ReserveTime)) - } - if !newBufferBalance.Equal(streamRecord.BufferBalance) { - streamRecord.StaticBalance = streamRecord.StaticBalance.Sub(newBufferBalance).Add(streamRecord.BufferBalance) - streamRecord.BufferBalance = newBufferBalance - } + // because reserve time could be changed, so we need to re-calculate buffer balance even rate change is zero + streamRecord.NetflowRate = streamRecord.NetflowRate.Add(change.RateChange) + newBufferBalance := sdkmath.ZeroInt() + if streamRecord.NetflowRate.IsNegative() { + newBufferBalance = streamRecord.NetflowRate.Abs().Mul(sdkmath.NewIntFromUint64(params.VersionedParams.ReserveTime)) + } + if !newBufferBalance.Equal(streamRecord.BufferBalance) { + streamRecord.StaticBalance = streamRecord.StaticBalance.Sub(newBufferBalance).Add(streamRecord.BufferBalance) + streamRecord.BufferBalance = newBufferBalance } // update static balance if !change.StaticBalanceChange.IsZero() { @@ -351,7 +349,7 @@ func (k Keeper) TryResumeStreamRecord(ctx sdk.Context, streamRecord *types.Strea } exists := k.ExistsAutoResumeRecord(ctx, 0, sdk.MustAccAddressFromHex(streamRecord.Account)) - if exists { // the account is resuming or settling + if exists { return fmt.Errorf("stream account %s status is resuming, please wait", streamRecord.Account) } From efa923a84e6a40b5217462f701a3a29d316aea26 Mon Sep 17 00:00:00 2001 From: mocky-b Date: Thu, 20 Jul 2023 16:29:53 +0800 Subject: [PATCH 23/33] 1. add TestStorageBill_MigrationBucket --- e2e/tests/storage_bill_test.go | 155 ++++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 1 deletion(-) diff --git a/e2e/tests/storage_bill_test.go b/e2e/tests/storage_bill_test.go index 14d41836e..5552942b9 100644 --- a/e2e/tests/storage_bill_test.go +++ b/e2e/tests/storage_bill_test.go @@ -9,6 +9,7 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/bnb-chain/greenfield/e2e/core" "github.com/bnb-chain/greenfield/sdk/keys" @@ -106,7 +107,6 @@ func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithoutPriceChange() { s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) - //distBucketName := s.createBucket(sp, user0, 0) distBucketName := bucketName distObjectName := storagetestutils.GenRandomObjectName() @@ -513,6 +513,159 @@ func (s *PaymentTestSuite) TestStorageBill_UpdatePaymentAddress() { s.SendTxBlockWithExpectErrorString(msgUpdateBucketInfo, user, "apply user flows list failed") } + +func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { + var err error + ctx := context.Background() + primarySP := s.PickStorageProvider() + s.RecoverSPPrice(primarySP) + //primarySP = s.StorageProviders[1] + gvg, found := primarySP.GetFirstGlobalVirtualGroup() + s.Require().True(found) + queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: gvg.FamilyId, + }) + s.Require().NoError(err) + family := queryFamilyResponse.GlobalVirtualGroupFamily + user0 := s.GenAndChargeAccounts(1, 1000000)[0] + + streamAddresses := []string{ + user0.GetAddr().String(), + family.VirtualPaymentAddress, + gvg.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + + paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) + s.T().Logf("paymentParams %s, err: %v", paymentParams, err) + s.Require().NoError(err) + + bucketName := s.createBucket(primarySP, user0, 0) + bucketInfo, err := s.Client.HeadBucket(context.Background(), &storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + }) + + // create object with none zero payload size + streamRecordsBefore := s.getStreamRecords(streamAddresses) + _, _, objectName, objectId, checksums, payloadSize := s.createObject(user0, bucketName, false) + + // assertions + streamRecordsAfter := s.getStreamRecords(streamAddresses) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + lockFee := s.calculateLockFee(primarySP, bucketName, objectName, payloadSize) + s.Require().Equal(streamRecordsAfter.User.LockBalance.Sub(streamRecordsBefore.User.LockBalance), lockFee) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate).Int64(), int64(0)) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate).Int64(), int64(0)) + + // case: seal object without price change + s.sealObject(primarySP, gvg, bucketName, objectName, objectId, checksums) + + // assertions + streamRecordsAfter = s.getStreamRecords(streamAddresses) + gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(primarySP, bucketName, objectName, payloadSize) + s.T().Logf("gvgFamilyRate: %v, gvgRate: %v, taxRate: %v, userTotalRate: %v", gvgFamilyRate, gvgRate, taxRate, userTotalRate) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + + dstPrimarySP := s.CreateNewStorageProvider() + + s.RecoverSPPrice(dstPrimarySP) + // migrate bucket + msgMigrationBucket := storagetypes.NewMsgMigrateBucket(user0.GetAddr(), bucketName, dstPrimarySP.Info.Id) + msgMigrationBucket.DstPrimarySpApproval.ExpiredHeight = math.MaxInt + msgMigrationBucket.DstPrimarySpApproval.Sig, err = dstPrimarySP.ApprovalKey.Sign(msgMigrationBucket.GetApprovalBytes()) + s.SendTxBlock(user0, msgMigrationBucket) + s.Require().NoError(err) + + // cancel migration bucket + msgCancelMigrationBucket := storagetypes.NewMsgCancelMigrateBucket(user0.GetAddr(), bucketName) + s.SendTxBlock(user0, msgCancelMigrationBucket) + s.Require().NoError(err) + + // complete migration bucket + var secondarySPIDs []uint32 + var secondarySPs []*core.StorageProvider + + for _, ssp := range s.StorageProviders { + if ssp.Info.Id != primarySP.Info.Id { + secondarySPIDs = append(secondarySPIDs, ssp.Info.Id) + secondarySPs = append(secondarySPs, ssp) + } + if len(secondarySPIDs) == 5 { + break + } + } + gvgID, _ := s.BaseSuite.CreateGlobalVirtualGroup(dstPrimarySP, 0, secondarySPIDs, 1) + gvgResp, err := s.Client.VirtualGroupQueryClient.GlobalVirtualGroup(context.Background(), &virtualgrouptypes.QueryGlobalVirtualGroupRequest{ + GlobalVirtualGroupId: gvgID, + }) + s.Require().NoError(err) + dstGVG := gvgResp.GlobalVirtualGroup + s.Require().True(found) + // create object + //s.BaseSuite.CreateObject(user0, dstPrimarySP, gvgID, storagetestutils.GenRandomBucketName(), storagetestutils.GenRandomObjectName()) + + //gvg = dstGVG + queryFamilyResponse, err = s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ + FamilyId: dstGVG.FamilyId, + }) + s.Require().NoError(err) + family = queryFamilyResponse.GlobalVirtualGroupFamily + streamAddresses = []string{ + user0.GetAddr().String(), + family.VirtualPaymentAddress, + dstGVG.VirtualPaymentAddress, + paymenttypes.ValidatorTaxPoolAddress.String(), + } + streamRecordsBefore = s.getStreamRecords(streamAddresses) + // construct the signatures + var gvgMappings []*storagetypes.GVGMapping + gvgMappings = append(gvgMappings, &storagetypes.GVGMapping{SrcGlobalVirtualGroupId: gvg.Id, DstGlobalVirtualGroupId: dstGVG.Id}) + for _, gvgMapping := range gvgMappings { + migrationBucketSignHash := storagetypes.NewSecondarySpMigrationBucketSignDoc(s.GetChainID(), bucketInfo.BucketInfo.Id, dstPrimarySP.Info.Id, gvgMapping.SrcGlobalVirtualGroupId, gvgMapping.DstGlobalVirtualGroupId).GetBlsSignHash() + secondarySigs := make([][]byte, 0) + secondarySPBlsPubKeys := make([]bls.PublicKey, 0) + for _, ssp := range secondarySPs { + sig, err := core.BlsSignAndVerify(ssp, migrationBucketSignHash) + s.Require().NoError(err) + secondarySigs = append(secondarySigs, sig) + pk, err := bls.PublicKeyFromBytes(ssp.BlsKey.PubKey().Bytes()) + s.Require().NoError(err) + secondarySPBlsPubKeys = append(secondarySPBlsPubKeys, pk) + } + aggBlsSig, err := core.BlsAggregateAndVerify(secondarySPBlsPubKeys, migrationBucketSignHash, secondarySigs) + s.Require().NoError(err) + gvgMapping.SecondarySpBlsSignature = aggBlsSig + } + + // send msgMigrationBucket + msgMigrationBucket = storagetypes.NewMsgMigrateBucket(user0.GetAddr(), bucketName, dstPrimarySP.Info.Id) + msgMigrationBucket.DstPrimarySpApproval.ExpiredHeight = math.MaxInt + msgMigrationBucket.DstPrimarySpApproval.Sig, err = dstPrimarySP.ApprovalKey.Sign(msgMigrationBucket.GetApprovalBytes()) + s.SendTxBlock(user0, msgMigrationBucket) + s.Require().NoError(err) + + // complete MigrationBucket + msgCompleteMigrationBucket := storagetypes.NewMsgCompleteMigrateBucket(dstPrimarySP.OperatorKey.GetAddr(), bucketName, dstGVG.FamilyId, gvgMappings) + s.SendTxBlock(dstPrimarySP.OperatorKey, msgCompleteMigrationBucket) + streamRecordsAfter = s.getStreamRecords(streamAddresses) + gvgFamilyRate, gvgRate, taxRate, userTotalRate = s.calculateStorageRates(primarySP, bucketName, objectName, payloadSize) + s.T().Logf("gvgFamilyRate: %v, gvgRate: %v, taxRate: %v, userTotalRate: %v", gvgFamilyRate, gvgRate, taxRate, userTotalRate) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + +} + func (s *PaymentTestSuite) RecoverSPPrice(sp *core.StorageProvider) { ctx := context.Background() From 0e49a976be0da88ed5c153bb36b1ccce2bdcf98d Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Thu, 20 Jul 2023 17:05:24 +0800 Subject: [PATCH 24/33] fix ut --- e2e/tests/storage_bill_test.go | 1 + x/payment/keeper/stream_record_test.go | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/e2e/tests/storage_bill_test.go b/e2e/tests/storage_bill_test.go index 5552942b9..71f338139 100644 --- a/e2e/tests/storage_bill_test.go +++ b/e2e/tests/storage_bill_test.go @@ -544,6 +544,7 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { bucketInfo, err := s.Client.HeadBucket(context.Background(), &storagetypes.QueryHeadBucketRequest{ BucketName: bucketName, }) + s.Require().NoError(err) // create object with none zero payload size streamRecordsBefore := s.getStreamRecords(streamAddresses) diff --git a/x/payment/keeper/stream_record_test.go b/x/payment/keeper/stream_record_test.go index bedbc6f3b..a726888d4 100644 --- a/x/payment/keeper/stream_record_test.go +++ b/x/payment/keeper/stream_record_test.go @@ -267,10 +267,9 @@ func TestTryResumeStreamRecord_ResumeInMultipleBlocks_BalanceNotEnoughFinally(t keeper.AutoResume(ctx) userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) - require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) + require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) require.Equal(t, userStreamRecord.NetflowRate, rate.Neg()) require.Equal(t, userStreamRecord.FrozenNetflowRate, sdkmath.ZeroInt()) - require.True(t, userStreamRecord.StaticBalance.IsNegative()) // the static balance becomes negative gvg1StreamRecord, _ := keeper.GetStreamRecord(ctx, gvg1) require.True(t, gvg1StreamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE) @@ -456,6 +455,7 @@ func TestAutoSettle_SettleInOneBlock(t *testing.T) { Addr: user.String(), }) + ctx = ctx.WithValue(types.ForceUpdateStreamRecordKey, true) keeper.AutoSettle(ctx) userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) @@ -563,6 +563,7 @@ func TestAutoSettle_SettleInMultipleBlocks(t *testing.T) { Addr: user.String(), }) + ctx = ctx.WithValue(types.ForceUpdateStreamRecordKey, true) keeper.AutoSettle(ctx) // this is for settle stream, it is counted userStreamRecord, _ = keeper.GetStreamRecord(ctx, user) require.True(t, userStreamRecord.Status == types.STREAM_ACCOUNT_STATUS_FROZEN) From 1ea7cb750a44e68a68d325c24ef94ef328fddfec Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Thu, 20 Jul 2023 20:27:11 +0800 Subject: [PATCH 25/33] fix calculation precision issue --- e2e/tests/payment_test.go | 28 ++++++++++++++++------------ x/storage/keeper/payment.go | 34 +++++++++++++++------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 3a489e0b0..ac394792e 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -3204,11 +3204,12 @@ func (s *PaymentTestSuite) calculateLockFee(sp *core.StorageProvider, bucketName s.Require().NoError(err) secondarySpCount := storageParams.Params.VersionedParams.RedundantDataChunkNum + storageParams.Params.VersionedParams.RedundantParityChunkNum - chargeSize := int64(s.getChargeSize(payloadSize)) + chargeSize := s.getChargeSize(payloadSize) _, primaryPrice, secondaryPrice := s.getPrices(sp, headBucketExtraResponse.ExtraInfo.PriceTime) - gvgFamilyRate := primaryPrice.MulInt64(chargeSize).TruncateInt() - gvgRate := secondaryPrice.MulInt64(chargeSize * int64(secondarySpCount)).TruncateInt() + gvgFamilyRate := primaryPrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() + gvgRate := secondaryPrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() + gvgRate = gvgRate.MulRaw(int64(secondarySpCount)) taxRate := params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() return gvgFamilyRate.Add(gvgRate).Add(taxRate).MulRaw(int64(params.VersionedParams.ReserveTime)) } @@ -3280,8 +3281,8 @@ func (s *PaymentTestSuite) calculateStorageRates(sp *core.StorageProvider, bucke } headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) s.Require().NoError(err) - gvgCount := len(headObjectResponse.GlobalVirtualGroup.SecondarySpIds) - fmt.Println("gvgCount", gvgCount) + secondarySpCount := len(headObjectResponse.GlobalVirtualGroup.SecondarySpIds) + fmt.Println("secondarySpCount", secondarySpCount) headBucketRequest := storagetypes.QueryHeadBucketRequest{ BucketName: bucketName, @@ -3289,11 +3290,12 @@ func (s *PaymentTestSuite) calculateStorageRates(sp *core.StorageProvider, bucke headBucketResponse, err := s.Client.HeadBucket(ctx, &headBucketRequest) s.Require().NoError(err) - chargeSize := int64(s.getChargeSize(payloadSize)) + chargeSize := s.getChargeSize(payloadSize) _, primaryPrice, secondaryPrice := s.getPrices(sp, headBucketResponse.BucketInfo.CreateAt) - gvgFamilyRate := primaryPrice.MulInt64(chargeSize).TruncateInt() - gvgRate := secondaryPrice.MulInt64(chargeSize * int64(gvgCount)).TruncateInt() + gvgFamilyRate := primaryPrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() + gvgRate := secondaryPrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() + gvgRate = gvgRate.MulRaw(int64(secondarySpCount)) taxRate := params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() return gvgFamilyRate, gvgRate, taxRate, gvgFamilyRate.Add(gvgRate).Add(taxRate) } @@ -3307,13 +3309,15 @@ func (s *PaymentTestSuite) calculateStorageRatesCurrentTimestamp(sp *core.Storag } headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) s.Require().NoError(err) - gvgCount := len(headObjectResponse.GlobalVirtualGroup.SecondarySpIds) + secondarySpCount := len(headObjectResponse.GlobalVirtualGroup.SecondarySpIds) + fmt.Println("secondarySpCount", secondarySpCount) - chargeSize := int64(s.getChargeSize(payloadSize)) + chargeSize := s.getChargeSize(payloadSize) _, primaryPrice, secondaryPrice := s.getPrices(sp, time.Now().Unix()) - gvgFamilyRate := primaryPrice.MulInt64(chargeSize).TruncateInt() - gvgRate := secondaryPrice.MulInt64(chargeSize * int64(gvgCount)).TruncateInt() + gvgFamilyRate := primaryPrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() + gvgRate := secondaryPrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() + gvgRate = gvgRate.MulRaw(int64(secondarySpCount)) taxRate := params.VersionedParams.ValidatorTaxRate.MulInt(gvgFamilyRate.Add(gvgRate)).TruncateInt() return gvgFamilyRate, gvgRate, taxRate, gvgFamilyRate.Add(gvgRate).Add(taxRate) } diff --git a/x/storage/keeper/payment.go b/x/storage/keeper/payment.go index 42c4a5b50..c55e5c74c 100644 --- a/x/storage/keeper/payment.go +++ b/x/storage/keeper/payment.go @@ -189,7 +189,7 @@ func (k Keeper) IsPriceChanged(ctx sdk.Context, primarySpId uint32, priceTime in return !(prePrice.ReadPrice.Equal(currentPrice.ReadPrice) && prePrice.PrimaryStorePrice.Equal(currentPrice.PrimaryStorePrice) && prePrice.SecondaryStorePrice.Equal(currentPrice.SecondaryStorePrice) && - preParams.ValidatorTaxRate == currentParams.ValidatorTaxRate), + preParams.ValidatorTaxRate.Equal(currentParams.ValidatorTaxRate)), prePrice.ReadPrice, prePrice.PrimaryStorePrice, prePrice.SecondaryStorePrice, @@ -389,12 +389,6 @@ func (k Keeper) ChargeViaObjectChange(ctx sdk.Context, bucketInfo *storagetypes. return fmt.Errorf("get storage price failed: %w", err) } - // primary sp total rate - primaryTotalFlowRate := sdk.ZeroInt() - - // secondary sp total rate - secondaryTotalFlowRate := sdk.ZeroInt() - var lvg *storagetypes.LocalVirtualGroup for _, l := range internalBucketInfo.LocalVirtualGroups { if l.Id == objectInfo.LocalVirtualGroupId { @@ -406,7 +400,10 @@ func (k Keeper) ChargeViaObjectChange(ctx sdk.Context, bucketInfo *storagetypes. // primary sp primaryRate := price.PrimaryStorePrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() if primaryRate.IsPositive() { - primaryTotalFlowRate = primaryTotalFlowRate.Add(primaryRate) + userFlows.Flows = append(userFlows.Flows, types.OutFlow{ + ToAddress: gvgFamily.VirtualPaymentAddress, + Rate: primaryRate, + }) } //secondary sp @@ -422,21 +419,13 @@ func (k Keeper) ChargeViaObjectChange(ctx sdk.Context, bucketInfo *storagetypes. ToAddress: gvg.VirtualPaymentAddress, Rate: secondaryRate, }) - secondaryTotalFlowRate = secondaryTotalFlowRate.Add(secondaryRate) - } - - if primaryTotalFlowRate.IsPositive() { - userFlows.Flows = append(userFlows.Flows, types.OutFlow{ - ToAddress: gvgFamily.VirtualPaymentAddress, - Rate: primaryTotalFlowRate, - }) } versionedParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, internalBucketInfo.PriceTime) if err != nil { return fmt.Errorf("failed to get validator tax rate: %w, time: %d", err, internalBucketInfo.PriceTime) } - validatorTaxRate := versionedParams.ValidatorTaxRate.MulInt(primaryTotalFlowRate.Add(secondaryTotalFlowRate)).TruncateInt() + validatorTaxRate := versionedParams.ValidatorTaxRate.MulInt(primaryRate.Add(secondaryRate)).TruncateInt() if validatorTaxRate.IsPositive() { userFlows.Flows = append(userFlows.Flows, types.OutFlow{ ToAddress: types.ValidatorTaxPoolAddress.String(), @@ -591,13 +580,20 @@ func (k Keeper) GetObjectLockFee(ctx sdk.Context, primarySpId uint32, priceTime if err != nil { return amount, fmt.Errorf("get charge size error: %w", err) } + + primaryRate := price.PrimaryStorePrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() + secondarySPNum := int64(k.GetExpectSecondarySPNumForECObject(ctx, priceTime)) - rate := price.PrimaryStorePrice.Add(price.SecondaryStorePrice.MulInt64(secondarySPNum)).MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() + secondaryRate := price.SecondaryStorePrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() + secondaryRate = secondaryRate.MulRaw(int64(secondarySPNum)) + versionedParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, priceTime) if err != nil { return amount, fmt.Errorf("get versioned reserve time error: %w", err) } - rate = versionedParams.ValidatorTaxRate.MulInt(rate).TruncateInt().Add(rate) // should also lock for validator tax pool + validatorTaxRate := versionedParams.ValidatorTaxRate.MulInt(primaryRate.Add(secondaryRate)).TruncateInt() + + rate := primaryRate.Add(secondaryRate).Add(validatorTaxRate) // should also lock for validator tax pool amount = rate.Mul(sdkmath.NewIntFromUint64(versionedParams.ReserveTime)) return amount, nil } From 170499f423684e7b485088bfa54b8cd2e8fee1d4 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Thu, 20 Jul 2023 20:40:57 +0800 Subject: [PATCH 26/33] refine query api --- app/reconciliation.go | 3 +- e2e/tests/bridge_test.go | 2 +- e2e/tests/payment_test.go | 20 +- proto/greenfield/storage/query.proto | 16 +- sdk/client/gnfd_tm.go | 3 +- sdk/client/gnfd_tm_test.go | 2 +- x/challenge/keeper/msg_server_attest.go | 2 +- x/storage/keeper/grpc_query.go | 4 +- x/storage/keeper/payment.go | 20 +- x/storage/types/query.pb.go | 395 +++++++++++++++--------- x/virtualgroup/keeper/payment_test.go | 11 +- 11 files changed, 290 insertions(+), 188 deletions(-) diff --git a/app/reconciliation.go b/app/reconciliation.go index 1a2d915c4..8043ec7b9 100644 --- a/app/reconciliation.go +++ b/app/reconciliation.go @@ -7,10 +7,11 @@ import ( "fmt" "cosmossdk.io/math" - paymenttypes "github.com/bnb-chain/greenfield/x/payment/types" "github.com/cosmos/cosmos-sdk/store/iavl" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + paymenttypes "github.com/bnb-chain/greenfield/x/payment/types" ) const reconStoreKey = "reconciliation" diff --git a/e2e/tests/bridge_test.go b/e2e/tests/bridge_test.go index 8d48447b8..4d6df2237 100644 --- a/e2e/tests/bridge_test.go +++ b/e2e/tests/bridge_test.go @@ -8,7 +8,6 @@ import ( "time" sdkmath "cosmossdk.io/math" - gnfdtypes "github.com/bnb-chain/greenfield/sdk/types" "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/tx" @@ -22,6 +21,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/bnb-chain/greenfield/e2e/core" + gnfdtypes "github.com/bnb-chain/greenfield/sdk/types" types2 "github.com/bnb-chain/greenfield/sdk/types" bridgetypes "github.com/bnb-chain/greenfield/x/bridge/types" ) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index ac394792e..f2fbd7cf4 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -11,9 +11,18 @@ import ( "testing" "time" + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + "github.com/prysmaticlabs/prysm/crypto/bls" + "github.com/samber/lo" "github.com/stretchr/testify/suite" - sdkmath "cosmossdk.io/math" "github.com/bnb-chain/greenfield/e2e/core" "github.com/bnb-chain/greenfield/sdk/keys" "github.com/bnb-chain/greenfield/sdk/types" @@ -23,15 +32,6 @@ import ( sptypes "github.com/bnb-chain/greenfield/x/sp/types" storagetypes "github.com/bnb-chain/greenfield/x/storage/types" virtualgrouptypes "github.com/bnb-chain/greenfield/x/virtualgroup/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/tx" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" - v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" - "github.com/prysmaticlabs/prysm/crypto/bls" - "github.com/samber/lo" ) type StreamRecords struct { diff --git a/proto/greenfield/storage/query.proto b/proto/greenfield/storage/query.proto index 467233a64..411f7f931 100644 --- a/proto/greenfield/storage/query.proto +++ b/proto/greenfield/storage/query.proto @@ -330,17 +330,27 @@ message QueryIsPriceChangedResponse { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; - string new_read_price = 5 [ + string current_validator_tax_rate = 5 [ (cosmos_proto.scalar) = "cosmos.Dec", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; - string new_primary_store_price = 6 [ + string new_read_price = 6 [ (cosmos_proto.scalar) = "cosmos.Dec", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; - string new_secondary_store_price = 7 [ + string new_primary_store_price = 7 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string new_secondary_store_price = 8 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string new_validator_tax_rate = 9 [ (cosmos_proto.scalar) = "cosmos.Dec", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false diff --git a/sdk/client/gnfd_tm.go b/sdk/client/gnfd_tm.go index 429554cd7..a3558e039 100644 --- a/sdk/client/gnfd_tm.go +++ b/sdk/client/gnfd_tm.go @@ -4,9 +4,8 @@ import ( "context" "encoding/hex" - "github.com/cometbft/cometbft/votepool" - ctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cometbft/cometbft/votepool" ) // GetBlock by height, gets the latest block if height is nil diff --git a/sdk/client/gnfd_tm_test.go b/sdk/client/gnfd_tm_test.go index 08b8fad80..861f112ec 100644 --- a/sdk/client/gnfd_tm_test.go +++ b/sdk/client/gnfd_tm_test.go @@ -7,10 +7,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/stretchr/testify/assert" "github.com/bnb-chain/greenfield/sdk/client/test" "github.com/bnb-chain/greenfield/sdk/keys" - "github.com/stretchr/testify/assert" ) func TestTmClient(t *testing.T) { diff --git a/x/challenge/keeper/msg_server_attest.go b/x/challenge/keeper/msg_server_attest.go index 1386f880f..74b52918d 100644 --- a/x/challenge/keeper/msg_server_attest.go +++ b/x/challenge/keeper/msg_server_attest.go @@ -6,7 +6,6 @@ import ( "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" - storagetypes "github.com/bnb-chain/greenfield/x/storage/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" @@ -14,6 +13,7 @@ import ( "github.com/bnb-chain/greenfield/x/challenge/types" paymentmoduletypes "github.com/bnb-chain/greenfield/x/payment/types" sptypes "github.com/bnb-chain/greenfield/x/sp/types" + storagetypes "github.com/bnb-chain/greenfield/x/storage/types" ) // Attest handles user's request for attesting a challenge. diff --git a/x/storage/keeper/grpc_query.go b/x/storage/keeper/grpc_query.go index e17d4f715..2570efd89 100644 --- a/x/storage/keeper/grpc_query.go +++ b/x/storage/keeper/grpc_query.go @@ -101,7 +101,7 @@ func (k Keeper) QueryIsPriceChanged(c context.Context, req *types.QueryIsPriceCh primarySp := k.MustGetPrimarySPForBucket(ctx, bucketInfo) internalBucketInfo := k.MustGetInternalBucketInfo(ctx, bucketInfo.Id) - changed, currentRead, currentPrimary, currentSecondary, newRead, newPrimary, newSecondary, err := k.IsPriceChanged(ctx, primarySp.Id, internalBucketInfo.PriceTime) + changed, currentRead, currentPrimary, currentSecondary, currentTaxRate, newRead, newPrimary, newSecondary, newTaxRate, err := k.IsPriceChanged(ctx, primarySp.Id, internalBucketInfo.PriceTime) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -111,8 +111,10 @@ func (k Keeper) QueryIsPriceChanged(c context.Context, req *types.QueryIsPriceCh CurrentReadPrice: currentRead, CurrentPrimaryStorePrice: currentPrimary, CurrentSecondaryStorePrice: currentSecondary, + CurrentValidatorTaxRate: currentTaxRate, NewReadPrice: newRead, NewPrimaryStorePrice: newPrimary, NewSecondaryStorePrice: newSecondary, + NewValidatorTaxRate: newTaxRate, }, nil } diff --git a/x/storage/keeper/payment.go b/x/storage/keeper/payment.go index c55e5c74c..abfee9faf 100644 --- a/x/storage/keeper/payment.go +++ b/x/storage/keeper/payment.go @@ -160,42 +160,38 @@ func (k Keeper) UnlockAndChargeObjectStoreFee(ctx sdk.Context, primarySpId uint3 return k.ChargeObjectStoreFee(ctx, primarySpId, bucketInfo, internalBucketInfo, objectInfo) } -func (k Keeper) IsPriceChanged(ctx sdk.Context, primarySpId uint32, priceTime int64) (bool, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, error) { +func (k Keeper) IsPriceChanged(ctx sdk.Context, primarySpId uint32, priceTime int64) (bool, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, error) { prePrice, err := k.paymentKeeper.GetStoragePrice(ctx, types.StoragePriceParams{ PrimarySp: primarySpId, PriceTime: priceTime, }) if err != nil { - return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get previous storage price failed: %w", err) + return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), err } currentPrice, err := k.paymentKeeper.GetStoragePrice(ctx, types.StoragePriceParams{ PrimarySp: primarySpId, PriceTime: ctx.BlockTime().Unix(), }) if err != nil { - return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get current storage price failed: %w", err) + return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), err } preParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, priceTime) if err != nil { - return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get previous payment params failed: %w", err) + return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), err } currentParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, ctx.BlockTime().Unix()) if err != nil { - return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), fmt.Errorf("get current payment params failed: %w", err) + return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), err } return !(prePrice.ReadPrice.Equal(currentPrice.ReadPrice) && prePrice.PrimaryStorePrice.Equal(currentPrice.PrimaryStorePrice) && prePrice.SecondaryStorePrice.Equal(currentPrice.SecondaryStorePrice) && preParams.ValidatorTaxRate.Equal(currentParams.ValidatorTaxRate)), - prePrice.ReadPrice, - prePrice.PrimaryStorePrice, - prePrice.SecondaryStorePrice, - currentPrice.ReadPrice, - currentPrice.PrimaryStorePrice, - currentPrice.SecondaryStorePrice, + prePrice.ReadPrice, prePrice.PrimaryStorePrice, prePrice.SecondaryStorePrice, preParams.ValidatorTaxRate, + currentPrice.ReadPrice, currentPrice.PrimaryStorePrice, currentPrice.SecondaryStorePrice, currentParams.ValidatorTaxRate, nil } @@ -206,7 +202,7 @@ func (k Keeper) ChargeObjectStoreFee(ctx sdk.Context, primarySpId uint32, bucket return fmt.Errorf("get charge size error: %w", err) } - priceChanged, _, _, _, _, _, _, err := k.IsPriceChanged(ctx, primarySpId, internalBucketInfo.PriceTime) + priceChanged, _, _, _, _, _, _, _, _, err := k.IsPriceChanged(ctx, primarySpId, internalBucketInfo.PriceTime) if err != nil { return fmt.Errorf("check whether price changed error: %w", err) } diff --git a/x/storage/types/query.pb.go b/x/storage/types/query.pb.go index b6f5667a0..8a84a7bcb 100644 --- a/x/storage/types/query.pb.go +++ b/x/storage/types/query.pb.go @@ -1850,9 +1850,11 @@ type QueryIsPriceChangedResponse struct { CurrentReadPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=current_read_price,json=currentReadPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"current_read_price"` CurrentPrimaryStorePrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=current_primary_store_price,json=currentPrimaryStorePrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"current_primary_store_price"` CurrentSecondaryStorePrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=current_secondary_store_price,json=currentSecondaryStorePrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"current_secondary_store_price"` - NewReadPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=new_read_price,json=newReadPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"new_read_price"` - NewPrimaryStorePrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=new_primary_store_price,json=newPrimaryStorePrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"new_primary_store_price"` - NewSecondaryStorePrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=new_secondary_store_price,json=newSecondaryStorePrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"new_secondary_store_price"` + CurrentValidatorTaxRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=current_validator_tax_rate,json=currentValidatorTaxRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"current_validator_tax_rate"` + NewReadPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=new_read_price,json=newReadPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"new_read_price"` + NewPrimaryStorePrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=new_primary_store_price,json=newPrimaryStorePrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"new_primary_store_price"` + NewSecondaryStorePrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,8,opt,name=new_secondary_store_price,json=newSecondaryStorePrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"new_secondary_store_price"` + NewValidatorTaxRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,9,opt,name=new_validator_tax_rate,json=newValidatorTaxRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"new_validator_tax_rate"` } func (m *QueryIsPriceChangedResponse) Reset() { *m = QueryIsPriceChangedResponse{} } @@ -1940,148 +1942,151 @@ func init() { func init() { proto.RegisterFile("greenfield/storage/query.proto", fileDescriptor_b1b80b580af04cb0) } var fileDescriptor_b1b80b580af04cb0 = []byte{ - // 2243 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x5a, 0xcb, 0x6f, 0x1c, 0x49, - 0x19, 0x4f, 0xdb, 0x89, 0x63, 0x97, 0x4d, 0x12, 0x0a, 0xef, 0xae, 0x33, 0x89, 0x27, 0x49, 0x2f, - 0x24, 0xde, 0x6c, 0x3c, 0x1d, 0x3b, 0x31, 0xc2, 0x64, 0x13, 0x64, 0x6f, 0x6c, 0x33, 0x52, 0x1e, - 0x66, 0x62, 0x05, 0x11, 0x09, 0xb5, 0x6a, 0xba, 0x6b, 0x26, 0xbd, 0x9e, 0xe9, 0xea, 0x74, 0xf7, - 0xc4, 0x3b, 0x3b, 0x1a, 0x21, 0xf6, 0x00, 0x1c, 0x11, 0x08, 0x69, 0x85, 0x40, 0x02, 0x21, 0x10, - 0x70, 0x41, 0xa0, 0xbd, 0x70, 0xe2, 0xc2, 0x61, 0x25, 0x84, 0xb4, 0x5a, 0x2e, 0x68, 0x0f, 0x2b, - 0x94, 0xf0, 0x1f, 0xf0, 0x0f, 0xa0, 0xae, 0xfa, 0xba, 0xbb, 0xfa, 0x31, 0xd3, 0xe3, 0xf5, 0x9c, - 0x32, 0x53, 0xf3, 0x3d, 0x7e, 0xdf, 0xa3, 0xbe, 0xaa, 0xfa, 0xc5, 0xa8, 0xdc, 0x74, 0x29, 0xb5, - 0x1b, 0x16, 0x6d, 0x99, 0x9a, 0xe7, 0x33, 0x97, 0x34, 0xa9, 0xf6, 0xac, 0x43, 0xdd, 0x6e, 0xc5, - 0x71, 0x99, 0xcf, 0x30, 0x8e, 0x7f, 0xaf, 0xc0, 0xef, 0xa5, 0xab, 0x06, 0xf3, 0xda, 0xcc, 0xd3, - 0xea, 0xc4, 0x03, 0x61, 0xed, 0xf9, 0x4a, 0x9d, 0xfa, 0x64, 0x45, 0x73, 0x48, 0xd3, 0xb2, 0x89, - 0x6f, 0x31, 0x5b, 0xe8, 0x97, 0xce, 0x0a, 0x59, 0x9d, 0x7f, 0xd3, 0xc4, 0x17, 0xf8, 0x69, 0xbe, - 0xc9, 0x9a, 0x4c, 0xac, 0x07, 0x9f, 0x60, 0xf5, 0x7c, 0x93, 0xb1, 0x66, 0x8b, 0x6a, 0xc4, 0xb1, - 0x34, 0x62, 0xdb, 0xcc, 0xe7, 0xd6, 0x42, 0x1d, 0x55, 0x82, 0xeb, 0x50, 0xb7, 0x6d, 0x79, 0x9e, - 0xc5, 0x6c, 0xcd, 0x60, 0xed, 0x76, 0xe4, 0xf2, 0x52, 0xbe, 0x8c, 0xdf, 0x75, 0x68, 0x68, 0xe6, - 0x42, 0x4e, 0xd4, 0x0e, 0x71, 0x49, 0x3b, 0x14, 0xc8, 0x4b, 0x8b, 0x6c, 0xe0, 0x75, 0xe9, 0xf7, - 0xe7, 0x96, 0xeb, 0x77, 0x48, 0xab, 0xe9, 0xb2, 0x8e, 0x23, 0x0b, 0xa9, 0xf3, 0x08, 0x7f, 0x2b, - 0xc8, 0xce, 0x2e, 0xb7, 0x5c, 0xa3, 0xcf, 0x3a, 0xd4, 0xf3, 0xd5, 0x87, 0xe8, 0x4b, 0x89, 0x55, - 0xcf, 0x61, 0xb6, 0x47, 0xf1, 0xd7, 0xd0, 0x94, 0x40, 0xb0, 0xa0, 0x5c, 0x54, 0x96, 0x66, 0x57, - 0x4b, 0x95, 0x6c, 0xe6, 0x2b, 0x42, 0x67, 0xf3, 0xf8, 0x47, 0x9f, 0x5d, 0x38, 0x56, 0x03, 0x79, - 0xf5, 0x36, 0x5a, 0x94, 0x0c, 0x6e, 0x76, 0xf7, 0xac, 0x36, 0xf5, 0x7c, 0xd2, 0x76, 0xc0, 0x23, - 0x3e, 0x8f, 0x66, 0xfc, 0x70, 0x8d, 0x5b, 0x9f, 0xac, 0xc5, 0x0b, 0xea, 0x13, 0x54, 0x1e, 0xa4, - 0x7e, 0x64, 0x68, 0xeb, 0xe8, 0x55, 0x6e, 0xfb, 0x9b, 0x94, 0x98, 0x9b, 0x1d, 0x63, 0x9f, 0xfa, - 0x21, 0xa6, 0x0b, 0x68, 0xb6, 0xce, 0x17, 0x74, 0x9b, 0xb4, 0x29, 0x37, 0x3c, 0x53, 0x43, 0x62, - 0xe9, 0x01, 0x69, 0x53, 0x75, 0x1d, 0x95, 0x52, 0xaa, 0x9b, 0xdd, 0xaa, 0x19, 0xaa, 0x9f, 0x43, - 0x33, 0xa0, 0x6e, 0x99, 0xa0, 0x3c, 0x2d, 0x16, 0xaa, 0xa6, 0xfa, 0x04, 0xbd, 0x96, 0xf1, 0x0a, - 0xa1, 0x7c, 0x23, 0x72, 0x6b, 0xd9, 0x0d, 0x06, 0xf1, 0x94, 0xf3, 0xe2, 0x11, 0x8a, 0x55, 0xbb, - 0xc1, 0x42, 0x58, 0xc1, 0x67, 0xf5, 0x89, 0x14, 0xd1, 0xc3, 0xfa, 0x3b, 0xd4, 0x18, 0x39, 0xa2, - 0x40, 0x80, 0x71, 0x0d, 0x21, 0x30, 0x21, 0x04, 0xc4, 0x52, 0x26, 0x64, 0x61, 0x3b, 0x15, 0x32, - 0xa8, 0xc7, 0x21, 0x8b, 0x85, 0xaa, 0xa9, 0xfe, 0x55, 0x91, 0x62, 0x0e, 0x71, 0xc5, 0x31, 0x87, - 0x8a, 0x05, 0x31, 0x0b, 0x45, 0x11, 0x33, 0x8b, 0x3e, 0xe3, 0xef, 0xa2, 0xf9, 0x66, 0x8b, 0xd5, - 0x49, 0x4b, 0x87, 0x56, 0xd7, 0x79, 0xaf, 0xf3, 0x08, 0x66, 0x57, 0xdf, 0x94, 0x2d, 0xc9, 0x7b, - 0xa1, 0xb2, 0xc3, 0x95, 0x1e, 0x8b, 0xa5, 0x9d, 0x60, 0xa9, 0x86, 0x9b, 0x99, 0x35, 0x95, 0x00, - 0xf4, 0x7b, 0x96, 0xe7, 0x8b, 0xac, 0x87, 0x7b, 0x05, 0x6f, 0x23, 0x14, 0x4f, 0x14, 0x40, 0x7e, - 0xb9, 0x02, 0x53, 0x24, 0x18, 0x3f, 0x15, 0x31, 0xab, 0x60, 0xfc, 0x54, 0x76, 0x49, 0x93, 0x82, - 0x6e, 0x4d, 0xd2, 0x54, 0x7f, 0xa7, 0xa0, 0x85, 0xac, 0x0f, 0xc8, 0xcf, 0x06, 0x9a, 0x93, 0x7a, - 0x22, 0x68, 0xf2, 0xc9, 0x11, 0x9a, 0x62, 0x36, 0x6e, 0x0a, 0x0f, 0xef, 0x24, 0x70, 0x8a, 0xbc, - 0x5c, 0x29, 0xc4, 0x29, 0xfc, 0x27, 0x80, 0xbe, 0xaf, 0x48, 0xc9, 0x10, 0xe5, 0x18, 0x77, 0x32, - 0xd2, 0x8d, 0x3a, 0x91, 0xd9, 0x7a, 0x3f, 0x52, 0xd0, 0xa5, 0x34, 0x88, 0xcd, 0x2e, 0xc4, 0x6e, - 0x8e, 0x1b, 0x4e, 0x62, 0x2b, 0x4f, 0xa4, 0xb6, 0x72, 0xa2, 0x70, 0x51, 0x3e, 0xe2, 0xc2, 0x49, - 0x8d, 0x3d, 0xb4, 0x70, 0x52, 0x67, 0xcf, 0xc6, 0x9d, 0x3d, 0xc6, 0xc2, 0x5d, 0x43, 0xa7, 0x39, - 0xce, 0x07, 0xdb, 0x7b, 0x61, 0x82, 0xce, 0xa2, 0x69, 0x9f, 0xed, 0x53, 0x3b, 0xde, 0xaf, 0x27, - 0xf9, 0xf7, 0xaa, 0xa9, 0x7e, 0x07, 0xa6, 0x88, 0xc8, 0x29, 0xd7, 0x89, 0x36, 0xeb, 0x4c, 0x9b, - 0xfa, 0x44, 0x37, 0x89, 0x4f, 0x20, 0xa9, 0xea, 0xe0, 0x4e, 0xbc, 0x4f, 0x7d, 0x72, 0x97, 0xf8, - 0xa4, 0x36, 0xdd, 0x86, 0x4f, 0x91, 0x69, 0x11, 0xf1, 0xe7, 0x31, 0x2d, 0x34, 0x73, 0x4c, 0x7f, - 0x1b, 0xbd, 0xc2, 0x4d, 0xf3, 0x6d, 0x2b, 0x5b, 0xbe, 0x93, 0xb5, 0x7c, 0x29, 0xcf, 0x32, 0x57, - 0xcc, 0x31, 0xfc, 0x7d, 0x05, 0x9d, 0x17, 0x67, 0x10, 0x6b, 0x59, 0x46, 0x77, 0x9b, 0xb9, 0x1b, - 0x86, 0xc1, 0x3a, 0x76, 0x34, 0x5b, 0x4b, 0x68, 0xda, 0xa5, 0x1e, 0xeb, 0xb8, 0x46, 0x38, 0x58, - 0xa3, 0xef, 0x78, 0x0b, 0x7d, 0xd1, 0x71, 0x2d, 0xdb, 0xb0, 0x1c, 0xd2, 0xd2, 0x89, 0x69, 0xba, - 0xd4, 0xf3, 0x44, 0x1f, 0x6d, 0x2e, 0x7c, 0xf2, 0xe1, 0xf2, 0x3c, 0x14, 0x73, 0x43, 0xfc, 0xf2, - 0xc8, 0x77, 0x2d, 0xbb, 0x59, 0x3b, 0x13, 0xa9, 0xc0, 0xba, 0xfa, 0x38, 0x3c, 0x45, 0x33, 0x10, - 0x20, 0xc8, 0x35, 0x34, 0xe5, 0xf0, 0xdf, 0x20, 0xc2, 0x45, 0x39, 0xc2, 0xf8, 0x9e, 0x51, 0x11, - 0x06, 0x6a, 0x20, 0xac, 0x7e, 0x1a, 0xc6, 0xf6, 0x98, 0xba, 0x56, 0xa3, 0xbb, 0x1b, 0x09, 0x86, - 0xb1, 0xdd, 0x44, 0xd3, 0xcc, 0xa1, 0x2e, 0xf1, 0x99, 0x2b, 0x62, 0x1b, 0x02, 0x3b, 0x92, 0x2c, - 0xdc, 0xc4, 0xe9, 0xd3, 0x66, 0x32, 0x7d, 0xda, 0xe0, 0x4d, 0x34, 0x4b, 0x8c, 0xa0, 0x77, 0xf5, - 0xe0, 0xce, 0xb2, 0x70, 0xfc, 0xa2, 0xb2, 0x74, 0x2a, 0x59, 0x36, 0x29, 0xa8, 0x0d, 0x2e, 0xb9, - 0xd7, 0x75, 0x68, 0x0d, 0x91, 0xe8, 0x73, 0x94, 0xb4, 0x6c, 0x6c, 0x71, 0xd2, 0x68, 0xa3, 0x41, - 0x0d, 0x9f, 0x87, 0x76, 0x6a, 0x60, 0xd2, 0xb6, 0xb8, 0x50, 0x0d, 0x84, 0xd5, 0x67, 0xd0, 0x69, - 0xc1, 0x69, 0x26, 0x0e, 0x0e, 0x48, 0xd6, 0x3a, 0x9a, 0xe5, 0x67, 0x8b, 0xce, 0x0e, 0x6c, 0x5a, - 0x9c, 0x2f, 0xc4, 0x85, 0x1f, 0x06, 0xb2, 0x78, 0x11, 0x89, 0x6f, 0x72, 0xc2, 0x66, 0xf8, 0x0a, - 0x1f, 0x7a, 0x8f, 0xa5, 0x83, 0x1d, 0x5c, 0x42, 0x0c, 0x6f, 0x85, 0x8a, 0xd2, 0xf1, 0xb9, 0x38, - 0xb0, 0xbd, 0xf9, 0x8c, 0x11, 0x76, 0xf9, 0x85, 0xe1, 0xe7, 0x0a, 0xc4, 0x12, 0x4c, 0xb0, 0x44, - 0x2c, 0xe3, 0x1a, 0xa0, 0xa9, 0x9c, 0x4c, 0x8c, 0x9e, 0x13, 0xf5, 0xd7, 0x0a, 0x44, 0x2d, 0x81, - 0x83, 0xa8, 0x77, 0x72, 0xd0, 0x7d, 0x9e, 0xc9, 0x88, 0xef, 0x84, 0xf0, 0xc4, 0x90, 0x9e, 0xe0, - 0x43, 0xba, 0x20, 0x7f, 0x28, 0xca, 0x9f, 0xa7, 0xfe, 0x41, 0x41, 0xe7, 0x92, 0x95, 0xb9, 0x4f, - 0xdb, 0x75, 0xea, 0x86, 0x69, 0xbc, 0x8e, 0xa6, 0xda, 0x7c, 0xa1, 0xb0, 0x1b, 0x40, 0xee, 0x08, - 0x09, 0x4b, 0x35, 0xd1, 0x64, 0xba, 0x89, 0x28, 0xec, 0xf5, 0x0c, 0x54, 0x48, 0xea, 0x16, 0x9a, - 0x13, 0xea, 0x12, 0xe2, 0xd4, 0x14, 0x96, 0x36, 0x85, 0x6c, 0x41, 0x20, 0x16, 0x5f, 0xd4, 0x06, - 0x5c, 0x14, 0xa3, 0x59, 0x95, 0xe8, 0xab, 0x61, 0xc3, 0xf2, 0x1a, 0xc2, 0xf1, 0xb0, 0x84, 0xb2, - 0x84, 0xa7, 0x6e, 0x3c, 0x13, 0x45, 0x21, 0x4c, 0x75, 0x0f, 0x32, 0x9f, 0xf6, 0x73, 0xb4, 0x89, - 0xb8, 0x06, 0x3d, 0x27, 0x96, 0x53, 0x57, 0x5c, 0x21, 0x23, 0x5d, 0x71, 0xc5, 0x42, 0xd5, 0x54, - 0x77, 0xe1, 0x66, 0x24, 0xab, 0x1d, 0x0d, 0xc8, 0x2f, 0x15, 0x78, 0x8a, 0xdd, 0x63, 0xc6, 0xfe, - 0x36, 0xa5, 0xf1, 0xc6, 0x0c, 0x92, 0xd4, 0x26, 0x6e, 0x57, 0xf7, 0x9c, 0xe8, 0x48, 0x51, 0x46, - 0x38, 0x52, 0x02, 0x9d, 0x47, 0x0e, 0xac, 0x07, 0xe1, 0x18, 0x2e, 0x25, 0x3e, 0xd5, 0x89, 0xcf, - 0x73, 0x3c, 0x59, 0x9b, 0x16, 0x0b, 0x1b, 0x3e, 0xbe, 0x84, 0xe6, 0x1c, 0xd2, 0x6d, 0x31, 0x62, - 0xea, 0x9e, 0xf5, 0x9e, 0xe8, 0xa5, 0xe3, 0xb5, 0x59, 0x58, 0x7b, 0x64, 0xbd, 0x47, 0xd5, 0x16, - 0x9a, 0x4f, 0xc2, 0x83, 0x70, 0xf7, 0xd0, 0x14, 0x69, 0x07, 0x67, 0x13, 0x60, 0x7a, 0x2b, 0x78, - 0x73, 0x7d, 0xfa, 0xd9, 0x85, 0xcb, 0x4d, 0xcb, 0x7f, 0xda, 0xa9, 0x57, 0x0c, 0xd6, 0x86, 0x97, - 0x36, 0xfc, 0xb3, 0xec, 0x99, 0xfb, 0xf0, 0x32, 0xad, 0xda, 0xfe, 0x27, 0x1f, 0x2e, 0x23, 0x88, - 0xa0, 0x6a, 0xfb, 0x35, 0xb0, 0xa5, 0xde, 0x91, 0xb6, 0x99, 0xb8, 0x5d, 0x6c, 0xbd, 0xeb, 0xbb, - 0x64, 0xe4, 0x07, 0x9b, 0xdc, 0xfb, 0x09, 0xfd, 0xa8, 0xf7, 0x11, 0x0d, 0x16, 0xe4, 0x31, 0x7a, - 0x39, 0x6f, 0x0c, 0x54, 0x6d, 0x9f, 0xba, 0x36, 0x69, 0x49, 0x97, 0xed, 0x19, 0xae, 0xc9, 0xe7, - 0xe9, 0x6d, 0xe8, 0xfd, 0xaa, 0xb7, 0xeb, 0x5a, 0x06, 0x7d, 0xfb, 0x29, 0xb1, 0x9b, 0xd4, 0x1c, - 0x19, 0xe5, 0xff, 0x4e, 0x40, 0x98, 0x69, 0x7d, 0x40, 0xb9, 0x80, 0x4e, 0x1a, 0x62, 0x89, 0x2b, - 0x4f, 0xd7, 0xc2, 0xaf, 0xf8, 0x1d, 0x84, 0x8d, 0x8e, 0xeb, 0x52, 0xdb, 0xd7, 0x5d, 0x4a, 0x4c, - 0xdd, 0x09, 0xd4, 0x61, 0x78, 0x1c, 0xa6, 0x02, 0x77, 0xa9, 0x21, 0x55, 0xe0, 0x2e, 0x35, 0x6a, - 0x67, 0xc0, 0x6e, 0x8d, 0x12, 0x93, 0x83, 0xc2, 0x3d, 0x74, 0x2e, 0xf4, 0x15, 0x75, 0xa2, 0xcf, - 0x5c, 0x0a, 0x4e, 0x27, 0xc7, 0xe0, 0x74, 0x01, 0x1c, 0xec, 0x42, 0xd7, 0x06, 0xe6, 0x85, 0xf3, - 0xef, 0xa1, 0xc5, 0xd0, 0xb9, 0x47, 0x0d, 0x66, 0x9b, 0x69, 0xf7, 0xc7, 0xc7, 0xe0, 0xbe, 0x04, - 0x2e, 0x1e, 0x85, 0x1e, 0x24, 0x00, 0x75, 0x74, 0xca, 0xa6, 0x07, 0x72, 0x96, 0x4f, 0x8c, 0xc1, - 0xe3, 0x9c, 0x4d, 0x0f, 0xe2, 0x0c, 0x7b, 0xe8, 0xb5, 0xc0, 0x47, 0x5e, 0x76, 0xa7, 0xc6, 0xe0, - 0x6c, 0xde, 0xa6, 0x07, 0xd9, 0xcc, 0x1e, 0xa0, 0xb3, 0x81, 0xd3, 0xfc, 0xac, 0x9e, 0x1c, 0x83, - 0xdb, 0x57, 0x6d, 0x7a, 0x90, 0x93, 0xd1, 0xd5, 0x1f, 0x2c, 0xa2, 0x13, 0xbc, 0xeb, 0x71, 0x1f, - 0x4d, 0x09, 0xa6, 0x06, 0xe7, 0xee, 0xbd, 0x2c, 0x5f, 0x55, 0xba, 0x52, 0x28, 0x27, 0xb6, 0x8e, - 0xaa, 0xbe, 0xff, 0xaf, 0xff, 0xfe, 0x74, 0xe2, 0x3c, 0x2e, 0x69, 0x03, 0xd9, 0x35, 0xfc, 0xa7, - 0xf0, 0xc2, 0x91, 0x61, 0x9b, 0xf0, 0x4a, 0x81, 0x9f, 0x2c, 0xb1, 0x55, 0x5a, 0x3d, 0x8c, 0x0a, - 0xa0, 0xac, 0x70, 0x94, 0x4b, 0xf8, 0xf2, 0x60, 0x94, 0x5a, 0x2f, 0x62, 0xc7, 0xfa, 0xf8, 0x17, - 0x0a, 0x42, 0xf1, 0x48, 0xc3, 0x57, 0x07, 0xba, 0xcc, 0x70, 0x5c, 0xa5, 0x37, 0x47, 0x92, 0x05, - 0x5c, 0x6b, 0x1c, 0x97, 0x86, 0x97, 0xf3, 0x70, 0x3d, 0x0d, 0xb6, 0x82, 0x98, 0x62, 0x5a, 0x4f, - 0x1a, 0x70, 0x7d, 0xfc, 0x7b, 0x05, 0x9d, 0x4a, 0x52, 0x64, 0xb8, 0x32, 0x82, 0x5b, 0xe9, 0xd4, - 0x3d, 0x1c, 0xcc, 0x75, 0x0e, 0xf3, 0x06, 0x5e, 0x29, 0x80, 0xa9, 0xd7, 0x83, 0x43, 0x3c, 0x02, - 0x6b, 0x99, 0x7d, 0xfc, 0x81, 0x82, 0xbe, 0x10, 0x5b, 0x7c, 0xb0, 0xbd, 0x87, 0x5f, 0x1f, 0xe8, - 0x39, 0x7e, 0x46, 0x97, 0x06, 0x67, 0x3c, 0xf3, 0x7a, 0x56, 0xbf, 0xca, 0xd1, 0x5d, 0xc7, 0x95, - 0x22, 0x74, 0x76, 0xc3, 0xd7, 0x7a, 0xe1, 0xeb, 0xbc, 0x8f, 0xff, 0x08, 0x45, 0x16, 0x4f, 0xdf, - 0x82, 0x22, 0x27, 0x68, 0xbf, 0x82, 0xec, 0x25, 0xa9, 0x38, 0xf5, 0x6d, 0x8e, 0xef, 0x36, 0xbe, - 0x35, 0x10, 0x9f, 0x78, 0xa0, 0x25, 0x8b, 0xac, 0xf5, 0xa4, 0x97, 0x5c, 0x5c, 0xf2, 0x98, 0x22, - 0x2c, 0x28, 0x79, 0x86, 0x4b, 0x3c, 0x1c, 0xe8, 0xe2, 0x92, 0x03, 0x3c, 0x28, 0x79, 0xc4, 0x52, - 0xc6, 0x25, 0x8f, 0xc8, 0x88, 0xa3, 0x96, 0x3c, 0xc3, 0x6a, 0x8c, 0x50, 0xf2, 0x30, 0x79, 0xc9, - 0x92, 0xff, 0x44, 0x41, 0xb3, 0x12, 0x1b, 0x88, 0x07, 0xa7, 0x24, 0xcb, 0x4b, 0x96, 0xae, 0x8d, - 0x26, 0x0c, 0x10, 0x97, 0x38, 0x44, 0x15, 0x5f, 0xcc, 0x83, 0xd8, 0xb2, 0x3c, 0x1f, 0xba, 0xd2, - 0xc3, 0xbf, 0x02, 0x50, 0xc0, 0x74, 0x15, 0x80, 0x4a, 0xf2, 0x83, 0x05, 0xa0, 0x52, 0xe4, 0xd9, - 0xf0, 0xbc, 0x71, 0x50, 0x22, 0x6f, 0x5e, 0x6a, 0xe0, 0xfc, 0x4d, 0x41, 0xaf, 0xe4, 0xf2, 0x82, - 0x78, 0x6d, 0x14, 0xff, 0x19, 0x1e, 0xf1, 0x90, 0xb0, 0x37, 0x38, 0xec, 0x5b, 0x78, 0xbd, 0x08, - 0x76, 0xd0, 0x8d, 0xd1, 0xf0, 0x49, 0xcc, 0xa1, 0x9f, 0x29, 0x68, 0x2e, 0x7a, 0xa0, 0x8d, 0xdc, - 0x93, 0x6f, 0x0c, 0x14, 0x4a, 0xd3, 0x61, 0x23, 0x8c, 0x72, 0x78, 0x43, 0x26, 0x3b, 0xf2, 0x1f, - 0x21, 0x53, 0x90, 0xa6, 0xa0, 0xf0, 0xf5, 0xc1, 0xe7, 0x5c, 0x3e, 0x61, 0x56, 0x5a, 0x39, 0x84, - 0x06, 0xa0, 0xbe, 0xcf, 0x51, 0xef, 0xe0, 0xad, 0xdc, 0x83, 0x51, 0x3c, 0xcb, 0x1a, 0xcc, 0xd5, - 0x89, 0xd0, 0xd3, 0x7a, 0xe1, 0xa3, 0xb2, 0xaf, 0xf5, 0x32, 0x04, 0x5c, 0x1f, 0xff, 0x53, 0x41, - 0x67, 0xd2, 0xb4, 0xd0, 0x90, 0x40, 0x06, 0xb0, 0x63, 0x43, 0x02, 0x19, 0xc4, 0x39, 0xa9, 0x7b, - 0x3c, 0x90, 0x07, 0xf8, 0x5e, 0x5e, 0x20, 0xcf, 0xb9, 0x96, 0x2e, 0xfd, 0xbf, 0x60, 0x2f, 0xe4, - 0xd4, 0xfa, 0xe9, 0xa9, 0x2b, 0xd1, 0x63, 0x7d, 0xfc, 0x5b, 0x05, 0xcd, 0x44, 0x5d, 0x83, 0xdf, - 0x18, 0x3a, 0x40, 0xe5, 0xe7, 0x78, 0xe9, 0xea, 0x28, 0xa2, 0xa3, 0x74, 0x77, 0xdc, 0x39, 0x5a, - 0x4f, 0xe2, 0x2f, 0xfa, 0xe1, 0x37, 0xb1, 0x3f, 0x3f, 0x50, 0xd0, 0x4c, 0xc4, 0xe6, 0x0c, 0xc1, - 0x99, 0xa6, 0xa3, 0x86, 0xe0, 0xcc, 0x90, 0x43, 0xea, 0x4d, 0x8e, 0xb3, 0x82, 0xaf, 0x0d, 0xdc, - 0x85, 0x39, 0x38, 0xf1, 0x6f, 0x14, 0x74, 0x3a, 0xc5, 0x8c, 0x60, 0xad, 0x38, 0x3b, 0x09, 0xba, - 0xa7, 0x74, 0x7d, 0x74, 0x05, 0x00, 0xbb, 0xcc, 0xc1, 0x5e, 0xc1, 0x5f, 0x29, 0xd8, 0x8e, 0xc0, - 0x0e, 0xfd, 0x3d, 0x64, 0x05, 0x92, 0xac, 0xc7, 0x90, 0x33, 0x36, 0x97, 0x86, 0x29, 0x69, 0x23, - 0xcb, 0x03, 0xce, 0x7b, 0x1c, 0xe7, 0x36, 0xbe, 0x5b, 0xb0, 0x01, 0x21, 0xb5, 0xb9, 0xdb, 0x2f, - 0xa4, 0x74, 0xfa, 0xc1, 0x51, 0x72, 0x3a, 0xc5, 0x97, 0x0c, 0xb9, 0xd7, 0x64, 0xb8, 0x98, 0x21, - 0x57, 0x84, 0x2c, 0x01, 0x33, 0xbc, 0x1f, 0x00, 0x3a, 0xdc, 0x0e, 0x22, 0x82, 0xa7, 0x8f, 0x7f, - 0xa8, 0xa0, 0x39, 0x99, 0xe0, 0xc0, 0x83, 0x9f, 0x1a, 0x49, 0x86, 0xa6, 0xb4, 0x54, 0x2c, 0x08, - 0xc8, 0xbe, 0xcc, 0x91, 0x95, 0xf1, 0xf9, 0xdc, 0x4e, 0x65, 0xc6, 0xbe, 0xde, 0xa0, 0x14, 0xff, - 0x19, 0x3a, 0x53, 0xe2, 0x2d, 0x0a, 0x3a, 0x33, 0xcb, 0x90, 0x14, 0x74, 0x66, 0x0e, 0x25, 0xa2, - 0xde, 0xe2, 0xe0, 0xd6, 0xf0, 0x8d, 0xa2, 0xeb, 0x2a, 0xa7, 0x3f, 0x52, 0x07, 0xf1, 0x5f, 0xc2, - 0x3e, 0x4d, 0x32, 0x19, 0x43, 0xfa, 0x34, 0x97, 0x32, 0x19, 0xd2, 0xa7, 0xf9, 0x14, 0x89, 0xfa, - 0x75, 0x8e, 0xfa, 0x26, 0x5e, 0xcd, 0x43, 0x6d, 0x79, 0xe2, 0x39, 0xab, 0x03, 0x6d, 0x92, 0x04, - 0xbd, 0x59, 0xfd, 0xe8, 0x45, 0x59, 0xf9, 0xf8, 0x45, 0x59, 0xf9, 0xcf, 0x8b, 0xb2, 0xf2, 0xe3, - 0x97, 0xe5, 0x63, 0x1f, 0xbf, 0x2c, 0x1f, 0xfb, 0xf7, 0xcb, 0xf2, 0xb1, 0x27, 0x9a, 0xf4, 0xe0, - 0xad, 0xdb, 0xf5, 0x65, 0xe3, 0x29, 0xb1, 0x6c, 0xd9, 0xc3, 0xbb, 0xc9, 0x3f, 0xc4, 0xa8, 0x4f, - 0xf1, 0x3f, 0xb2, 0xb8, 0xf1, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf4, 0xd1, 0x6a, 0xa9, 0xc2, - 0x22, 0x00, 0x00, + // 2290 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x5a, 0xdb, 0x6f, 0xdc, 0x58, + 0x19, 0xaf, 0x93, 0x6e, 0x9a, 0x9c, 0x09, 0x6d, 0x39, 0x9b, 0xdd, 0xa6, 0xd3, 0x66, 0xda, 0x7a, + 0xa1, 0xcd, 0x76, 0x9b, 0x71, 0x93, 0x36, 0x88, 0xd0, 0x6d, 0x51, 0xb2, 0x4d, 0xc2, 0x48, 0xbd, + 0x04, 0x37, 0x0a, 0xa2, 0x12, 0xb2, 0xce, 0xd8, 0x67, 0xa6, 0xde, 0xcc, 0xd8, 0xae, 0xed, 0x69, + 0x3a, 0x3b, 0x1a, 0x21, 0xf6, 0x01, 0x78, 0x44, 0x20, 0xa4, 0x15, 0x02, 0x09, 0x84, 0x40, 0xc0, + 0x0b, 0x02, 0xed, 0x0b, 0x4f, 0xbc, 0xf0, 0xb0, 0x12, 0x42, 0x5a, 0x2d, 0x2f, 0x68, 0x1f, 0x56, + 0xd0, 0xf2, 0x87, 0xac, 0x7c, 0xce, 0x67, 0xfb, 0xf8, 0x32, 0xe3, 0xc9, 0x66, 0x9e, 0x3a, 0x3e, + 0xfe, 0x2e, 0xbf, 0xef, 0x72, 0xbe, 0x73, 0xfc, 0x6b, 0x50, 0xa5, 0xe9, 0x52, 0x6a, 0x35, 0x4c, + 0xda, 0x32, 0x14, 0xcf, 0xb7, 0x5d, 0xd2, 0xa4, 0xca, 0xd3, 0x0e, 0x75, 0xbb, 0x55, 0xc7, 0xb5, + 0x7d, 0x1b, 0xe3, 0xf8, 0x7d, 0x15, 0xde, 0x97, 0xaf, 0xea, 0xb6, 0xd7, 0xb6, 0x3d, 0xa5, 0x4e, + 0x3c, 0x10, 0x56, 0x9e, 0x2d, 0xd7, 0xa9, 0x4f, 0x96, 0x15, 0x87, 0x34, 0x4d, 0x8b, 0xf8, 0xa6, + 0x6d, 0x71, 0xfd, 0xf2, 0x59, 0x2e, 0xab, 0xb1, 0x27, 0x85, 0x3f, 0xc0, 0xab, 0xb9, 0xa6, 0xdd, + 0xb4, 0xf9, 0x7a, 0xf0, 0x0b, 0x56, 0xcf, 0x37, 0x6d, 0xbb, 0xd9, 0xa2, 0x0a, 0x71, 0x4c, 0x85, + 0x58, 0x96, 0xed, 0x33, 0x6b, 0xa1, 0x8e, 0x2c, 0xc0, 0x75, 0xa8, 0xdb, 0x36, 0x3d, 0xcf, 0xb4, + 0x2d, 0x45, 0xb7, 0xdb, 0xed, 0xc8, 0xe5, 0xa5, 0x7c, 0x19, 0xbf, 0xeb, 0xd0, 0xd0, 0xcc, 0x85, + 0x9c, 0xa8, 0x1d, 0xe2, 0x92, 0x76, 0x28, 0x90, 0x97, 0x16, 0xd1, 0xc0, 0x1b, 0xc2, 0xfb, 0x67, + 0xa6, 0xeb, 0x77, 0x48, 0xab, 0xe9, 0xda, 0x1d, 0x47, 0x14, 0x92, 0xe7, 0x10, 0xfe, 0x76, 0x90, + 0x9d, 0x1d, 0x66, 0x59, 0xa5, 0x4f, 0x3b, 0xd4, 0xf3, 0xe5, 0x87, 0xe8, 0xd5, 0xc4, 0xaa, 0xe7, + 0xd8, 0x96, 0x47, 0xf1, 0xd7, 0xd1, 0x14, 0x47, 0x30, 0x2f, 0x5d, 0x94, 0x16, 0x4b, 0x2b, 0xe5, + 0x6a, 0x36, 0xf3, 0x55, 0xae, 0xb3, 0x71, 0xfc, 0xa3, 0xcf, 0x2e, 0x1c, 0x53, 0x41, 0x5e, 0xbe, + 0x8d, 0x16, 0x04, 0x83, 0x1b, 0xdd, 0x5d, 0xb3, 0x4d, 0x3d, 0x9f, 0xb4, 0x1d, 0xf0, 0x88, 0xcf, + 0xa3, 0x19, 0x3f, 0x5c, 0x63, 0xd6, 0x27, 0xd5, 0x78, 0x41, 0x7e, 0x8c, 0x2a, 0x83, 0xd4, 0x8f, + 0x0c, 0x6d, 0x0d, 0xbd, 0xce, 0x6c, 0x7f, 0x8b, 0x12, 0x63, 0xa3, 0xa3, 0xef, 0x53, 0x3f, 0xc4, + 0x74, 0x01, 0x95, 0xea, 0x6c, 0x41, 0xb3, 0x48, 0x9b, 0x32, 0xc3, 0x33, 0x2a, 0xe2, 0x4b, 0x0f, + 0x48, 0x9b, 0xca, 0x6b, 0xa8, 0x9c, 0x52, 0xdd, 0xe8, 0xd6, 0x8c, 0x50, 0xfd, 0x1c, 0x9a, 0x01, + 0x75, 0xd3, 0x00, 0xe5, 0x69, 0xbe, 0x50, 0x33, 0xe4, 0xc7, 0xe8, 0x4c, 0xc6, 0x2b, 0x84, 0xf2, + 0xcd, 0xc8, 0xad, 0x69, 0x35, 0x6c, 0x88, 0xa7, 0x92, 0x17, 0x0f, 0x57, 0xac, 0x59, 0x0d, 0x3b, + 0x84, 0x15, 0xfc, 0x96, 0x1f, 0x0b, 0x11, 0x3d, 0xac, 0xbf, 0x4b, 0xf5, 0x91, 0x23, 0x0a, 0x04, + 0x6c, 0xa6, 0xc1, 0x05, 0x26, 0xb8, 0x00, 0x5f, 0xca, 0x84, 0xcc, 0x6d, 0xa7, 0x42, 0x06, 0xf5, + 0x38, 0x64, 0xbe, 0x50, 0x33, 0xe4, 0xbf, 0x49, 0x42, 0xcc, 0x21, 0xae, 0x38, 0xe6, 0x50, 0xb1, + 0x20, 0x66, 0xae, 0xc8, 0x63, 0xb6, 0xa3, 0xdf, 0xf8, 0x7b, 0x68, 0xae, 0xd9, 0xb2, 0xeb, 0xa4, + 0xa5, 0x41, 0xab, 0x6b, 0xac, 0xd7, 0x59, 0x04, 0xa5, 0x95, 0xb7, 0x44, 0x4b, 0xe2, 0x5e, 0xa8, + 0x6e, 0x33, 0xa5, 0x3d, 0xbe, 0xb4, 0x1d, 0x2c, 0xa9, 0xb8, 0x99, 0x59, 0x93, 0x09, 0x40, 0xbf, + 0x67, 0x7a, 0x3e, 0xcf, 0x7a, 0xb8, 0x57, 0xf0, 0x16, 0x42, 0xf1, 0x44, 0x01, 0xe4, 0x97, 0xab, + 0x30, 0x45, 0x82, 0xf1, 0x53, 0xe5, 0xb3, 0x0a, 0xc6, 0x4f, 0x75, 0x87, 0x34, 0x29, 0xe8, 0xaa, + 0x82, 0xa6, 0xfc, 0x7b, 0x09, 0xcd, 0x67, 0x7d, 0x40, 0x7e, 0xd6, 0xd1, 0xac, 0xd0, 0x13, 0x41, + 0x93, 0x4f, 0x8e, 0xd0, 0x14, 0xa5, 0xb8, 0x29, 0x3c, 0xbc, 0x9d, 0xc0, 0xc9, 0xf3, 0x72, 0xa5, + 0x10, 0x27, 0xf7, 0x9f, 0x00, 0xfa, 0xbe, 0x24, 0x24, 0x83, 0x97, 0x63, 0xdc, 0xc9, 0x48, 0x37, + 0xea, 0x44, 0x66, 0xeb, 0xfd, 0x58, 0x42, 0x97, 0xd2, 0x20, 0x36, 0xba, 0x10, 0xbb, 0x31, 0x6e, + 0x38, 0x89, 0xad, 0x3c, 0x91, 0xda, 0xca, 0x89, 0xc2, 0x45, 0xf9, 0x88, 0x0b, 0x27, 0x34, 0xf6, + 0xd0, 0xc2, 0x09, 0x9d, 0x5d, 0x8a, 0x3b, 0x7b, 0x8c, 0x85, 0xbb, 0x86, 0x4e, 0x31, 0x9c, 0x0f, + 0xb6, 0x76, 0xc3, 0x04, 0x9d, 0x45, 0xd3, 0xbe, 0xbd, 0x4f, 0xad, 0x78, 0xbf, 0x9e, 0x60, 0xcf, + 0x35, 0x43, 0xfe, 0x2e, 0x4c, 0x11, 0x9e, 0x53, 0xa6, 0x13, 0x6d, 0xd6, 0x99, 0x36, 0xf5, 0x89, + 0x66, 0x10, 0x9f, 0x40, 0x52, 0xe5, 0xc1, 0x9d, 0x78, 0x9f, 0xfa, 0xe4, 0x2e, 0xf1, 0x89, 0x3a, + 0xdd, 0x86, 0x5f, 0x91, 0x69, 0x1e, 0xf1, 0x17, 0x31, 0xcd, 0x35, 0x73, 0x4c, 0x7f, 0x07, 0xbd, + 0xc6, 0x4c, 0xb3, 0x6d, 0x2b, 0x5a, 0xbe, 0x93, 0xb5, 0x7c, 0x29, 0xcf, 0x32, 0x53, 0xcc, 0x31, + 0xfc, 0x03, 0x09, 0x9d, 0xe7, 0x67, 0x90, 0xdd, 0x32, 0xf5, 0xee, 0x96, 0xed, 0xae, 0xeb, 0xba, + 0xdd, 0xb1, 0xa2, 0xd9, 0x5a, 0x46, 0xd3, 0x2e, 0xf5, 0xec, 0x8e, 0xab, 0x87, 0x83, 0x35, 0x7a, + 0xc6, 0x9b, 0xe8, 0xcb, 0x8e, 0x6b, 0x5a, 0xba, 0xe9, 0x90, 0x96, 0x46, 0x0c, 0xc3, 0xa5, 0x9e, + 0xc7, 0xfb, 0x68, 0x63, 0xfe, 0x93, 0x0f, 0x97, 0xe6, 0xa0, 0x98, 0xeb, 0xfc, 0xcd, 0x23, 0xdf, + 0x35, 0xad, 0xa6, 0x7a, 0x3a, 0x52, 0x81, 0x75, 0x79, 0x2f, 0x3c, 0x45, 0x33, 0x10, 0x20, 0xc8, + 0x55, 0x34, 0xe5, 0xb0, 0x77, 0x10, 0xe1, 0x82, 0x18, 0x61, 0x7c, 0xcf, 0xa8, 0x72, 0x03, 0x2a, + 0x08, 0xcb, 0x9f, 0x86, 0xb1, 0xed, 0x51, 0xd7, 0x6c, 0x74, 0x77, 0x22, 0xc1, 0x30, 0xb6, 0x9b, + 0x68, 0xda, 0x76, 0xa8, 0x4b, 0x7c, 0xdb, 0xe5, 0xb1, 0x0d, 0x81, 0x1d, 0x49, 0x16, 0x6e, 0xe2, + 0xf4, 0x69, 0x33, 0x99, 0x3e, 0x6d, 0xf0, 0x06, 0x2a, 0x11, 0x3d, 0xe8, 0x5d, 0x2d, 0xb8, 0xb3, + 0xcc, 0x1f, 0xbf, 0x28, 0x2d, 0x9e, 0x4c, 0x96, 0x4d, 0x08, 0x6a, 0x9d, 0x49, 0xee, 0x76, 0x1d, + 0xaa, 0x22, 0x12, 0xfd, 0x8e, 0x92, 0x96, 0x8d, 0x2d, 0x4e, 0x1a, 0x6d, 0x34, 0xa8, 0xee, 0xb3, + 0xd0, 0x4e, 0x0e, 0x4c, 0xda, 0x26, 0x13, 0x52, 0x41, 0x58, 0x7e, 0x0a, 0x9d, 0x16, 0x9c, 0x66, + 0xfc, 0xe0, 0x80, 0x64, 0xad, 0xa1, 0x12, 0x3b, 0x5b, 0x34, 0xfb, 0xc0, 0xa2, 0xc5, 0xf9, 0x42, + 0x4c, 0xf8, 0x61, 0x20, 0x8b, 0x17, 0x10, 0x7f, 0x12, 0x13, 0x36, 0xc3, 0x56, 0xd8, 0xd0, 0xdb, + 0x13, 0x0e, 0x76, 0x70, 0x09, 0x31, 0xbc, 0x1d, 0x2a, 0x0a, 0xc7, 0xe7, 0xc2, 0xc0, 0xf6, 0x66, + 0x33, 0x86, 0xdb, 0x65, 0x17, 0x86, 0x5f, 0x48, 0x10, 0x4b, 0x30, 0xc1, 0x12, 0xb1, 0x8c, 0x6b, + 0x80, 0xa6, 0x72, 0x32, 0x31, 0x7a, 0x4e, 0xe4, 0xdf, 0x48, 0x10, 0xb5, 0x00, 0x0e, 0xa2, 0xde, + 0xce, 0x41, 0xf7, 0x45, 0x26, 0x23, 0xbe, 0x13, 0xc2, 0xe3, 0x43, 0x7a, 0x82, 0x0d, 0xe9, 0x82, + 0xfc, 0xa1, 0x28, 0x7f, 0x9e, 0xfc, 0x47, 0x09, 0x9d, 0x4b, 0x56, 0xe6, 0x3e, 0x6d, 0xd7, 0xa9, + 0x1b, 0xa6, 0xf1, 0x3a, 0x9a, 0x6a, 0xb3, 0x85, 0xc2, 0x6e, 0x00, 0xb9, 0x23, 0x24, 0x2c, 0xd5, + 0x44, 0x93, 0xe9, 0x26, 0xa2, 0xb0, 0xd7, 0x33, 0x50, 0x21, 0xa9, 0x9b, 0x68, 0x96, 0xab, 0x0b, + 0x88, 0x53, 0x53, 0x58, 0xd8, 0x14, 0xa2, 0x05, 0x8e, 0x98, 0x3f, 0xc8, 0x0d, 0xb8, 0x28, 0x46, + 0xb3, 0x2a, 0xd1, 0x57, 0xc3, 0x86, 0xe5, 0x35, 0x84, 0xe3, 0x61, 0x09, 0x65, 0x09, 0x4f, 0xdd, + 0x78, 0x26, 0xf2, 0x42, 0x18, 0xf2, 0x2e, 0x64, 0x3e, 0xed, 0xe7, 0x68, 0x13, 0x71, 0x15, 0x7a, + 0x8e, 0x2f, 0xa7, 0xae, 0xb8, 0x5c, 0x46, 0xb8, 0xe2, 0xf2, 0x85, 0x9a, 0x21, 0xef, 0xc0, 0xcd, + 0x48, 0x54, 0x3b, 0x1a, 0x90, 0x5f, 0x49, 0xf0, 0x29, 0x76, 0xcf, 0xd6, 0xf7, 0xb7, 0x28, 0x8d, + 0x37, 0x66, 0x90, 0xa4, 0x36, 0x71, 0xbb, 0x9a, 0xe7, 0x44, 0x47, 0x8a, 0x34, 0xc2, 0x91, 0x12, + 0xe8, 0x3c, 0x72, 0x60, 0x3d, 0x08, 0x47, 0x77, 0x29, 0xf1, 0xa9, 0x46, 0x7c, 0x96, 0xe3, 0x49, + 0x75, 0x9a, 0x2f, 0xac, 0xfb, 0xf8, 0x12, 0x9a, 0x75, 0x48, 0xb7, 0x65, 0x13, 0x43, 0xf3, 0xcc, + 0xf7, 0x78, 0x2f, 0x1d, 0x57, 0x4b, 0xb0, 0xf6, 0xc8, 0x7c, 0x8f, 0xca, 0x2d, 0x34, 0x97, 0x84, + 0x07, 0xe1, 0xee, 0xa2, 0x29, 0xd2, 0x0e, 0xce, 0x26, 0xc0, 0xf4, 0x76, 0xf0, 0xcd, 0xf5, 0xe9, + 0x67, 0x17, 0x2e, 0x37, 0x4d, 0xff, 0x49, 0xa7, 0x5e, 0xd5, 0xed, 0x36, 0x7c, 0x69, 0xc3, 0x3f, + 0x4b, 0x9e, 0xb1, 0x0f, 0x5f, 0xa6, 0x35, 0xcb, 0xff, 0xe4, 0xc3, 0x25, 0x04, 0x11, 0xd4, 0x2c, + 0x5f, 0x05, 0x5b, 0xf2, 0x1d, 0x61, 0x9b, 0xf1, 0xdb, 0xc5, 0xe6, 0x73, 0xdf, 0x25, 0x23, 0x7f, + 0xb0, 0x89, 0xbd, 0x9f, 0xd0, 0x8f, 0x7a, 0x1f, 0xd1, 0x60, 0x41, 0x1c, 0xa3, 0x97, 0xf3, 0xc6, + 0x40, 0xcd, 0xf2, 0xa9, 0x6b, 0x91, 0x96, 0x70, 0xd9, 0x9e, 0x61, 0x9a, 0x6c, 0x9e, 0xde, 0x86, + 0xde, 0xaf, 0x79, 0x3b, 0xae, 0xa9, 0xd3, 0x77, 0x9e, 0x10, 0xab, 0x49, 0x8d, 0x91, 0x51, 0xfe, + 0xef, 0x04, 0x84, 0x99, 0xd6, 0x07, 0x94, 0xf3, 0xe8, 0x84, 0xce, 0x97, 0x98, 0xf2, 0xb4, 0x1a, + 0x3e, 0xe2, 0x77, 0x11, 0xd6, 0x3b, 0xae, 0x4b, 0x2d, 0x5f, 0x73, 0x29, 0x31, 0x34, 0x27, 0x50, + 0x87, 0xe1, 0x71, 0x98, 0x0a, 0xdc, 0xa5, 0xba, 0x50, 0x81, 0xbb, 0x54, 0x57, 0x4f, 0x83, 0x5d, + 0x95, 0x12, 0x83, 0x81, 0xc2, 0x3d, 0x74, 0x2e, 0xf4, 0x15, 0x75, 0xa2, 0x6f, 0xbb, 0x14, 0x9c, + 0x4e, 0x8e, 0xc1, 0xe9, 0x3c, 0x38, 0xd8, 0x81, 0xae, 0x0d, 0xcc, 0x73, 0xe7, 0xdf, 0x47, 0x0b, + 0xa1, 0x73, 0x8f, 0xea, 0xb6, 0x65, 0xa4, 0xdd, 0x1f, 0x1f, 0x83, 0xfb, 0x32, 0xb8, 0x78, 0x14, + 0x7a, 0x10, 0x00, 0x74, 0x51, 0xf8, 0x56, 0x7b, 0x46, 0x5a, 0xa6, 0x11, 0x5c, 0x78, 0x34, 0x9f, + 0x3c, 0xd7, 0x5c, 0xe2, 0xd3, 0xf9, 0x57, 0xc6, 0xe0, 0xfd, 0x0c, 0xd8, 0xdf, 0x0b, 0xcd, 0xef, + 0x92, 0xe7, 0x2a, 0xf1, 0x29, 0xae, 0xa3, 0x93, 0x16, 0x3d, 0x10, 0x0b, 0x3c, 0x35, 0x06, 0x77, + 0xb3, 0x16, 0x3d, 0x88, 0x8b, 0xeb, 0xa1, 0x33, 0x81, 0x8f, 0xbc, 0xc2, 0x9e, 0x18, 0x83, 0xb3, + 0x39, 0x8b, 0x1e, 0x64, 0x8b, 0x7a, 0x80, 0xce, 0x06, 0x4e, 0xf3, 0x0b, 0x3a, 0x3d, 0x06, 0xb7, + 0xaf, 0x5b, 0xf4, 0x20, 0xaf, 0x98, 0x4f, 0x51, 0xf0, 0x26, 0xaf, 0x90, 0x33, 0x63, 0xf0, 0xfa, + 0xaa, 0x45, 0x0f, 0xd2, 0x45, 0x5c, 0xf9, 0xe1, 0x02, 0x7a, 0x85, 0xed, 0x71, 0xdc, 0x47, 0x53, + 0x9c, 0x97, 0xc2, 0xb9, 0x93, 0x26, 0xcb, 0xce, 0x95, 0xaf, 0x14, 0xca, 0xf1, 0x41, 0x21, 0xcb, + 0xef, 0xff, 0xfb, 0xff, 0x3f, 0x9b, 0x38, 0x8f, 0xcb, 0xca, 0x40, 0x2e, 0x11, 0xff, 0x39, 0xbc, + 0x5e, 0x65, 0xb8, 0x35, 0xbc, 0x5c, 0xe0, 0x27, 0x4b, 0xe3, 0x95, 0x57, 0x0e, 0xa3, 0x02, 0x28, + 0xab, 0x0c, 0xe5, 0x22, 0xbe, 0x3c, 0x18, 0xa5, 0xd2, 0x8b, 0xb8, 0xc0, 0x3e, 0xfe, 0xa5, 0x84, + 0x50, 0x3c, 0xc0, 0xf1, 0xd5, 0x81, 0x2e, 0x33, 0x8c, 0x5e, 0xf9, 0xad, 0x91, 0x64, 0x01, 0xd7, + 0x2a, 0xc3, 0xa5, 0xe0, 0xa5, 0x3c, 0x5c, 0x4f, 0x82, 0xdd, 0xc7, 0x67, 0xb6, 0xd2, 0x13, 0xc6, + 0x79, 0x1f, 0xff, 0x41, 0x42, 0x27, 0x93, 0x84, 0x20, 0xae, 0x8e, 0xe0, 0x56, 0xb8, 0x63, 0x1c, + 0x0e, 0xe6, 0x1a, 0x83, 0x79, 0x03, 0x2f, 0x17, 0xc0, 0xd4, 0xea, 0xc1, 0x95, 0x25, 0x02, 0x6b, + 0x1a, 0x7d, 0xfc, 0x81, 0x84, 0xbe, 0x14, 0x5b, 0x7c, 0xb0, 0xb5, 0x8b, 0xdf, 0x18, 0xe8, 0x39, + 0x26, 0x0d, 0xca, 0x83, 0x33, 0x9e, 0xe1, 0x0a, 0xe4, 0xaf, 0x31, 0x74, 0xd7, 0x71, 0xb5, 0x08, + 0x9d, 0xd5, 0xf0, 0x95, 0x5e, 0xc8, 0x45, 0xf4, 0xf1, 0x9f, 0xa0, 0xc8, 0xfc, 0x43, 0xbf, 0xa0, + 0xc8, 0x09, 0x92, 0xb3, 0x20, 0x7b, 0x49, 0xe2, 0x51, 0x7e, 0x87, 0xe1, 0xbb, 0x8d, 0x6f, 0x0d, + 0xc4, 0xc7, 0x3f, 0x47, 0x93, 0x45, 0x56, 0x7a, 0xc2, 0x77, 0x6b, 0x5c, 0xf2, 0x98, 0x10, 0x2d, + 0x28, 0x79, 0x86, 0x39, 0x3d, 0x1c, 0xe8, 0xe2, 0x92, 0x03, 0x3c, 0x28, 0x79, 0xc4, 0xc9, 0xc6, + 0x25, 0x8f, 0xa8, 0x97, 0xa3, 0x96, 0x3c, 0xc3, 0xe1, 0x8c, 0x50, 0xf2, 0x30, 0x79, 0xc9, 0x92, + 0xff, 0x54, 0x42, 0x25, 0x81, 0xfb, 0xc4, 0x83, 0x53, 0x92, 0x65, 0x61, 0xcb, 0xd7, 0x46, 0x13, + 0x06, 0x88, 0x8b, 0x0c, 0xa2, 0x8c, 0x2f, 0xe6, 0x41, 0x6c, 0x99, 0x9e, 0x0f, 0x5d, 0xe9, 0xe1, + 0x5f, 0x03, 0x28, 0xe0, 0xf5, 0x0a, 0x40, 0x25, 0xd9, 0xd0, 0x02, 0x50, 0x29, 0xaa, 0x70, 0x78, + 0xde, 0x18, 0x28, 0x9e, 0x37, 0x2f, 0x35, 0x70, 0xfe, 0x2e, 0xa1, 0xd7, 0x72, 0x59, 0x50, 0xbc, + 0x3a, 0x8a, 0xff, 0x0c, 0x6b, 0x7a, 0x48, 0xd8, 0xeb, 0x0c, 0xf6, 0x2d, 0xbc, 0x56, 0x04, 0x3b, + 0xe8, 0xc6, 0x68, 0xf8, 0x24, 0xe6, 0xd0, 0xcf, 0x25, 0x34, 0x1b, 0x7d, 0x8e, 0x8e, 0xdc, 0x93, + 0x6f, 0x0e, 0x14, 0x4a, 0x93, 0x7f, 0x23, 0x8c, 0x72, 0xf8, 0x62, 0x4e, 0x76, 0xe4, 0x3f, 0x43, + 0x5e, 0x24, 0x4d, 0xb8, 0xe1, 0xeb, 0x83, 0xcf, 0xb9, 0x7c, 0x7a, 0xb0, 0xbc, 0x7c, 0x08, 0x0d, + 0x40, 0x7d, 0x9f, 0xa1, 0xde, 0xc6, 0x9b, 0xb9, 0x07, 0x23, 0xff, 0x08, 0x6d, 0xd8, 0xae, 0x46, + 0xb8, 0x9e, 0xd2, 0x0b, 0x3f, 0xa1, 0xfb, 0x4a, 0x2f, 0x43, 0x37, 0xf6, 0xf1, 0xbf, 0x24, 0x74, + 0x3a, 0x4d, 0x82, 0x0d, 0x09, 0x64, 0x00, 0x17, 0x38, 0x24, 0x90, 0x41, 0x0c, 0x9b, 0xbc, 0xcb, + 0x02, 0x79, 0x80, 0xef, 0xe5, 0x05, 0xf2, 0x8c, 0x69, 0x69, 0xc2, 0xff, 0x82, 0xf6, 0x42, 0x06, + 0xb1, 0x9f, 0x9e, 0xba, 0x02, 0x19, 0xd8, 0xc7, 0xbf, 0x93, 0xd0, 0x4c, 0xd4, 0x35, 0xf8, 0xcd, + 0xa1, 0x03, 0x54, 0x24, 0x1f, 0xca, 0x57, 0x47, 0x11, 0x1d, 0xa5, 0xbb, 0xe3, 0xce, 0x51, 0x7a, + 0x02, 0x5b, 0xd3, 0x0f, 0x9f, 0xf8, 0xfe, 0xfc, 0x40, 0x42, 0x33, 0x11, 0x77, 0x35, 0x04, 0x67, + 0x9a, 0x7c, 0x1b, 0x82, 0x33, 0x43, 0x85, 0xc9, 0x37, 0x19, 0xce, 0x2a, 0xbe, 0x36, 0x70, 0x17, + 0xe6, 0xe0, 0xc4, 0xbf, 0x95, 0xd0, 0xa9, 0x14, 0x0f, 0x84, 0x95, 0xe2, 0xec, 0x24, 0xc8, 0xad, + 0xf2, 0xf5, 0xd1, 0x15, 0x00, 0xec, 0x12, 0x03, 0x7b, 0x05, 0x7f, 0xb5, 0x60, 0x3b, 0x02, 0x17, + 0xf6, 0x8f, 0x90, 0x03, 0x49, 0x72, 0x3c, 0x43, 0xce, 0xd8, 0x5c, 0xd2, 0xa9, 0xac, 0x8c, 0x2c, + 0x0f, 0x38, 0xef, 0x31, 0x9c, 0x5b, 0xf8, 0x6e, 0xc1, 0x06, 0x84, 0xd4, 0xe6, 0x6e, 0xbf, 0x90, + 0xc0, 0xea, 0x07, 0x47, 0xc9, 0xa9, 0x14, 0x3b, 0x34, 0xe4, 0x5e, 0x93, 0x61, 0x9e, 0x86, 0x5c, + 0x11, 0xb2, 0x74, 0xd3, 0xf0, 0x7e, 0x00, 0xe8, 0x70, 0x3b, 0x88, 0xe8, 0xac, 0x3e, 0xfe, 0x91, + 0x84, 0x66, 0x45, 0x3a, 0x07, 0x0f, 0xfe, 0xd4, 0x48, 0xf2, 0x51, 0xe5, 0xc5, 0x62, 0x41, 0x40, + 0xf6, 0x15, 0x86, 0xac, 0x82, 0xcf, 0xe7, 0x76, 0xaa, 0xad, 0xef, 0x6b, 0x0d, 0x4a, 0xf1, 0x5f, + 0xa0, 0x33, 0x05, 0x96, 0xa6, 0xa0, 0x33, 0xb3, 0x7c, 0x50, 0x41, 0x67, 0xe6, 0x10, 0x40, 0xf2, + 0x2d, 0x06, 0x6e, 0x15, 0xdf, 0x28, 0xba, 0xae, 0x32, 0xb2, 0x27, 0x75, 0x10, 0xff, 0x35, 0xec, + 0xd3, 0x24, 0x6f, 0x33, 0xa4, 0x4f, 0x73, 0x09, 0xa2, 0x21, 0x7d, 0x9a, 0x4f, 0x08, 0xc9, 0xdf, + 0x60, 0xa8, 0x6f, 0xe2, 0x95, 0x3c, 0xd4, 0xa6, 0xc7, 0xbf, 0xa0, 0x35, 0x20, 0x89, 0x92, 0xa0, + 0x37, 0x6a, 0x1f, 0xbd, 0xa8, 0x48, 0x1f, 0xbf, 0xa8, 0x48, 0xff, 0x7d, 0x51, 0x91, 0x7e, 0xf2, + 0xb2, 0x72, 0xec, 0xe3, 0x97, 0x95, 0x63, 0xff, 0x79, 0x59, 0x39, 0xf6, 0x58, 0x11, 0xbe, 0x76, + 0xeb, 0x56, 0x7d, 0x49, 0x7f, 0x42, 0x4c, 0x4b, 0xf4, 0xf0, 0x3c, 0xf9, 0x67, 0x27, 0xf5, 0x29, + 0xf6, 0x27, 0x25, 0x37, 0x3e, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x32, 0xdd, 0xcd, 0x59, 0xb0, 0x23, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -4358,6 +4363,16 @@ func (m *QueryIsPriceChangedResponse) MarshalToSizedBuffer(dAtA []byte) (int, er _ = i var l int _ = l + { + size := m.NewValidatorTaxRate.Size() + i -= size + if _, err := m.NewValidatorTaxRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a { size := m.NewSecondaryStorePrice.Size() i -= size @@ -4367,7 +4382,7 @@ func (m *QueryIsPriceChangedResponse) MarshalToSizedBuffer(dAtA []byte) (int, er i = encodeVarintQuery(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x3a + dAtA[i] = 0x42 { size := m.NewPrimaryStorePrice.Size() i -= size @@ -4377,7 +4392,7 @@ func (m *QueryIsPriceChangedResponse) MarshalToSizedBuffer(dAtA []byte) (int, er i = encodeVarintQuery(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x32 + dAtA[i] = 0x3a { size := m.NewReadPrice.Size() i -= size @@ -4387,6 +4402,16 @@ func (m *QueryIsPriceChangedResponse) MarshalToSizedBuffer(dAtA []byte) (int, er i = encodeVarintQuery(dAtA, i, uint64(size)) } i-- + dAtA[i] = 0x32 + { + size := m.CurrentValidatorTaxRate.Size() + i -= size + if _, err := m.CurrentValidatorTaxRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- dAtA[i] = 0x2a { size := m.CurrentSecondaryStorePrice.Size() @@ -5014,12 +5039,16 @@ func (m *QueryIsPriceChangedResponse) Size() (n int) { n += 1 + l + sovQuery(uint64(l)) l = m.CurrentSecondaryStorePrice.Size() n += 1 + l + sovQuery(uint64(l)) + l = m.CurrentValidatorTaxRate.Size() + n += 1 + l + sovQuery(uint64(l)) l = m.NewReadPrice.Size() n += 1 + l + sovQuery(uint64(l)) l = m.NewPrimaryStorePrice.Size() n += 1 + l + sovQuery(uint64(l)) l = m.NewSecondaryStorePrice.Size() n += 1 + l + sovQuery(uint64(l)) + l = m.NewValidatorTaxRate.Size() + n += 1 + l + sovQuery(uint64(l)) return n } @@ -8862,6 +8891,40 @@ func (m *QueryIsPriceChangedResponse) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentValidatorTaxRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.CurrentValidatorTaxRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field NewReadPrice", wireType) } @@ -8895,7 +8958,7 @@ func (m *QueryIsPriceChangedResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 6: + case 7: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field NewPrimaryStorePrice", wireType) } @@ -8929,7 +8992,7 @@ func (m *QueryIsPriceChangedResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 7: + case 8: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field NewSecondaryStorePrice", wireType) } @@ -8963,6 +9026,40 @@ func (m *QueryIsPriceChangedResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewValidatorTaxRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.NewValidatorTaxRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/virtualgroup/keeper/payment_test.go b/x/virtualgroup/keeper/payment_test.go index fef9f7627..a8acb37f7 100644 --- a/x/virtualgroup/keeper/payment_test.go +++ b/x/virtualgroup/keeper/payment_test.go @@ -4,14 +4,7 @@ import ( "errors" "testing" - "github.com/stretchr/testify/require" - "cosmossdk.io/math" - - "github.com/bnb-chain/greenfield/testutil/sample" - "github.com/bnb-chain/greenfield/x/challenge" - sptypes "github.com/bnb-chain/greenfield/x/sp/types" - "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/testutil" @@ -20,8 +13,12 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "github.com/bnb-chain/greenfield/testutil/sample" + "github.com/bnb-chain/greenfield/x/challenge" + sptypes "github.com/bnb-chain/greenfield/x/sp/types" "github.com/bnb-chain/greenfield/x/virtualgroup/keeper" "github.com/bnb-chain/greenfield/x/virtualgroup/types" ) From dad678caf16cfd289dbaf881f4ce09c7830ff066 Mon Sep 17 00:00:00 2001 From: mocky-b Date: Thu, 20 Jul 2023 22:14:46 +0800 Subject: [PATCH 27/33] 1. fix TestStorageBill_MigrationBucket assertion --- e2e/tests/payment_test.go | 26 ++++++++--------- e2e/tests/storage_bill_test.go | 53 +++++++++++++++++----------------- 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index f2fbd7cf4..832541494 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -1546,7 +1546,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreLessThanReserve } streamRecordsBefore := s.getStreamRecords(streamAddresses) _, _, userRateRead := s.calculateReadRates(sp, bucketName) - _, _, _, userRateStore := s.calculateStorageRates(sp, bucketName, objectName1, payloadSize) + _, _, _, userRateStore := s.calculateStorageRates(sp, bucketName, objectName1, payloadSize, 0) msgDeleteObject := storagetypes.NewMsgDeleteObject(user.GetAddr(), bucketName, objectName1) s.SendTxBlock(user, msgDeleteObject) @@ -1618,7 +1618,7 @@ func (s *PaymentTestSuite) TestStorageBill_DeleteObject_WithStoreMoreThanReserve } streamRecordsBefore := s.getStreamRecords(streamAddresses) _, _, userRateRead := s.calculateReadRates(sp, bucketName) - _, _, _, userRateStore := s.calculateStorageRates(sp, bucketName, objectName1, payloadSize) + _, _, _, userRateStore := s.calculateStorageRates(sp, bucketName, objectName1, payloadSize, 0) msgDeleteObject := storagetypes.NewMsgDeleteObject(user.GetAddr(), bucketName, objectName1) simulateResponse := s.SimulateTx(msgDeleteObject, user) @@ -1769,7 +1769,7 @@ func (s *PaymentTestSuite) TestStorageBill_CreateObject_WithZeroNoneZeroPayload( streamRecordsAfter := s.getStreamRecords(streamAddresses) s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) - gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize) + gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize, 0) s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) @@ -1946,7 +1946,7 @@ func (s *PaymentTestSuite) TestStorageBill_SealObject_WithoutPriceChange() { streamRecordsAfter = s.getStreamRecords(streamAddresses) s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) - gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize) + gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize, 0) s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) @@ -3270,9 +3270,7 @@ func (s *PaymentTestSuite) calculateReadRatesCurrentTimestamp(sp *core.StoragePr return gvgFamilyRate, taxRate, gvgFamilyRate.Add(taxRate) } -func (s *PaymentTestSuite) calculateStorageRates(sp *core.StorageProvider, bucketName, objectName string, payloadSize uint64) (sdkmath.Int, sdkmath.Int, sdkmath.Int, sdkmath.Int) { - ctx := context.Background() - +func (s *PaymentTestSuite) calculateStorageRates(sp *core.StorageProvider, bucketName, objectName string, payloadSize uint64, priceTime int64) (sdkmath.Int, sdkmath.Int, sdkmath.Int, sdkmath.Int) { params := s.queryParams() queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ @@ -3283,15 +3281,17 @@ func (s *PaymentTestSuite) calculateStorageRates(sp *core.StorageProvider, bucke s.Require().NoError(err) secondarySpCount := len(headObjectResponse.GlobalVirtualGroup.SecondarySpIds) fmt.Println("secondarySpCount", secondarySpCount) - - headBucketRequest := storagetypes.QueryHeadBucketRequest{ - BucketName: bucketName, + if priceTime == 0 { + headBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + headBucketResponse, err := s.Client.HeadBucket(context.Background(), &headBucketRequest) + s.Require().NoError(err) + priceTime = headBucketResponse.BucketInfo.CreateAt } - headBucketResponse, err := s.Client.HeadBucket(ctx, &headBucketRequest) - s.Require().NoError(err) chargeSize := s.getChargeSize(payloadSize) - _, primaryPrice, secondaryPrice := s.getPrices(sp, headBucketResponse.BucketInfo.CreateAt) + _, primaryPrice, secondaryPrice := s.getPrices(sp, priceTime) gvgFamilyRate := primaryPrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() gvgRate := secondaryPrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() diff --git a/e2e/tests/storage_bill_test.go b/e2e/tests/storage_bill_test.go index 71f338139..3966d8ba9 100644 --- a/e2e/tests/storage_bill_test.go +++ b/e2e/tests/storage_bill_test.go @@ -101,7 +101,7 @@ func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithoutPriceChange() { streamRecordsAfter = s.getStreamRecords(streamAddresses) s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) - gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize) + gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize, 0) s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) @@ -172,7 +172,7 @@ func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithPriceChange() { streamRecordsAfter = s.getStreamRecords(streamAddresses) s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) - gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize) + gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(sp, bucketName, objectName, payloadSize, 0) s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) @@ -201,7 +201,7 @@ func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithPriceChange() { streamRecordsAfterCopy := s.getStreamRecords(streamAddresses) s.Require().Equal(streamRecordsAfterCopy.User.StaticBalance, sdkmath.ZeroInt()) s.Require().Equal(streamRecordsAfterCopy.User.LockBalance, sdkmath.ZeroInt()) - gvgFamilyRate1, gvgRate1, taxRate1, userTotalRate1 := s.calculateStorageRates(sp, distBucketName, distObjectName, payloadSize) + gvgFamilyRate1, gvgRate1, taxRate1, userTotalRate1 := s.calculateStorageRates(sp, distBucketName, distObjectName, payloadSize, 0) s.Require().Equal(streamRecordsAfterCopy.GVGFamily.NetflowRate.Sub(streamRecordsAfter.GVGFamily.NetflowRate), gvgFamilyRate1) s.Require().Equal(streamRecordsAfterCopy.GVG.NetflowRate.Sub(streamRecordsAfter.GVG.NetflowRate), gvgRate1) s.Require().Equal(streamRecordsAfterCopy.Tax.NetflowRate.Sub(streamRecordsAfter.Tax.NetflowRate), taxRate1) @@ -519,7 +519,7 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { ctx := context.Background() primarySP := s.PickStorageProvider() s.RecoverSPPrice(primarySP) - //primarySP = s.StorageProviders[1] + gvg, found := primarySP.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -565,7 +565,7 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { // assertions streamRecordsAfter = s.getStreamRecords(streamAddresses) - gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(primarySP, bucketName, objectName, payloadSize) + gvgFamilyRate, gvgRate, taxRate, userTotalRate := s.calculateStorageRates(primarySP, bucketName, objectName, payloadSize, 0) s.T().Logf("gvgFamilyRate: %v, gvgRate: %v, taxRate: %v, userTotalRate: %v", gvgFamilyRate, gvgRate, taxRate, userTotalRate) s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) @@ -573,23 +573,12 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) - + taxRate0 := taxRate dstPrimarySP := s.CreateNewStorageProvider() s.RecoverSPPrice(dstPrimarySP) - // migrate bucket - msgMigrationBucket := storagetypes.NewMsgMigrateBucket(user0.GetAddr(), bucketName, dstPrimarySP.Info.Id) - msgMigrationBucket.DstPrimarySpApproval.ExpiredHeight = math.MaxInt - msgMigrationBucket.DstPrimarySpApproval.Sig, err = dstPrimarySP.ApprovalKey.Sign(msgMigrationBucket.GetApprovalBytes()) - s.SendTxBlock(user0, msgMigrationBucket) - s.Require().NoError(err) - - // cancel migration bucket - msgCancelMigrationBucket := storagetypes.NewMsgCancelMigrateBucket(user0.GetAddr(), bucketName) - s.SendTxBlock(user0, msgCancelMigrationBucket) - s.Require().NoError(err) - // complete migration bucket + // new sp CreateGlobalVirtualGroup var secondarySPIDs []uint32 var secondarySPs []*core.StorageProvider @@ -598,7 +587,7 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { secondarySPIDs = append(secondarySPIDs, ssp.Info.Id) secondarySPs = append(secondarySPs, ssp) } - if len(secondarySPIDs) == 5 { + if len(secondarySPIDs) == 6 { break } } @@ -609,10 +598,7 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { s.Require().NoError(err) dstGVG := gvgResp.GlobalVirtualGroup s.Require().True(found) - // create object - //s.BaseSuite.CreateObject(user0, dstPrimarySP, gvgID, storagetestutils.GenRandomBucketName(), storagetestutils.GenRandomObjectName()) - //gvg = dstGVG queryFamilyResponse, err = s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ FamilyId: dstGVG.FamilyId, }) @@ -624,6 +610,12 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { dstGVG.VirtualPaymentAddress, paymenttypes.ValidatorTaxPoolAddress.String(), } + fundAddress := primarySP.FundingKey.GetAddr() + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: fundAddress.String()} + + fundBalanceBefore, err := s.Client.BankQueryClient.Balance(context.Background(), &queryBalanceRequest) + s.Require().NoError(err) + streamRecordsBefore = s.getStreamRecords(streamAddresses) // construct the signatures var gvgMappings []*storagetypes.GVGMapping @@ -646,7 +638,7 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { } // send msgMigrationBucket - msgMigrationBucket = storagetypes.NewMsgMigrateBucket(user0.GetAddr(), bucketName, dstPrimarySP.Info.Id) + msgMigrationBucket := storagetypes.NewMsgMigrateBucket(user0.GetAddr(), bucketName, dstPrimarySP.Info.Id) msgMigrationBucket.DstPrimarySpApproval.ExpiredHeight = math.MaxInt msgMigrationBucket.DstPrimarySpApproval.Sig, err = dstPrimarySP.ApprovalKey.Sign(msgMigrationBucket.GetApprovalBytes()) s.SendTxBlock(user0, msgMigrationBucket) @@ -656,14 +648,21 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { msgCompleteMigrationBucket := storagetypes.NewMsgCompleteMigrateBucket(dstPrimarySP.OperatorKey.GetAddr(), bucketName, dstGVG.FamilyId, gvgMappings) s.SendTxBlock(dstPrimarySP.OperatorKey, msgCompleteMigrationBucket) streamRecordsAfter = s.getStreamRecords(streamAddresses) - gvgFamilyRate, gvgRate, taxRate, userTotalRate = s.calculateStorageRates(primarySP, bucketName, objectName, payloadSize) + fundBalanceAfter, err := s.Client.BankQueryClient.Balance(context.Background(), &queryBalanceRequest) + s.Require().NoError(err) + s.T().Logf("fundBalanceBefore: %v, fundBalanceAfter: %v, diff: %v", fundBalanceBefore, fundBalanceAfter, fundBalanceAfter.Balance.Amount.Sub(fundBalanceBefore.Balance.Amount)) + s.Require().True(fundBalanceAfter.Balance.Amount.Sub(fundBalanceBefore.Balance.Amount).GT(sdkmath.NewInt(0)), "migrate sp fund address need settle") + gvgFamilyRate, gvgRate, taxRate, userTotalRate = s.calculateStorageRates(dstPrimarySP, bucketName, objectName, payloadSize, time.Now().Unix()) s.T().Logf("gvgFamilyRate: %v, gvgRate: %v, taxRate: %v, userTotalRate: %v", gvgFamilyRate, gvgRate, taxRate, userTotalRate) + s.T().Logf("NetflowRate: %v, userTotalRate: %v, actual taxRate diff: %v, expect taxRate diff: %v", streamRecordsAfter.User.NetflowRate.Neg(), userTotalRate.Neg(), streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate.Sub(taxRate0)) + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) - s.Require().Equal(streamRecordsAfter.User.NetflowRate.Sub(streamRecordsBefore.User.NetflowRate), userTotalRate.Neg()) s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) - s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate) + // tax rate diff + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate.Sub(taxRate0)) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Neg(), userTotalRate.Abs()) } @@ -675,7 +674,7 @@ func (s *PaymentTestSuite) RecoverSPPrice(sp *core.StorageProvider) { Timestamp: time.Now().Unix(), }) s.Require().NoError(err) - recoverReadPrice, err := sdk.NewDecFromStr("0.0087") + recoverReadPrice, err := sdk.NewDecFromStr("100.0087") s.Require().NoError(err) msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ From f353db67dbd9cdbd984ad562b00a9d5bf924286a Mon Sep 17 00:00:00 2001 From: mocky-b Date: Fri, 21 Jul 2023 10:37:41 +0800 Subject: [PATCH 28/33] 1. add price change with TestStorageBill_MigrationBucket assertion --- e2e/tests/payment_test.go | 2 +- e2e/tests/storage_bill_test.go | 228 +++++++++++++++++++++------------ 2 files changed, 146 insertions(+), 84 deletions(-) diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 832541494..17133e33c 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -3292,7 +3292,7 @@ func (s *PaymentTestSuite) calculateStorageRates(sp *core.StorageProvider, bucke chargeSize := s.getChargeSize(payloadSize) _, primaryPrice, secondaryPrice := s.getPrices(sp, priceTime) - + s.T().Logf("===secondaryPrice: %v,primaryPrice: %v===", secondaryPrice, primaryPrice) gvgFamilyRate := primaryPrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() gvgRate := secondaryPrice.MulInt(sdkmath.NewIntFromUint64(chargeSize)).TruncateInt() gvgRate = gvgRate.MulRaw(int64(secondarySpCount)) diff --git a/e2e/tests/storage_bill_test.go b/e2e/tests/storage_bill_test.go index 3966d8ba9..3f63fe363 100644 --- a/e2e/tests/storage_bill_test.go +++ b/e2e/tests/storage_bill_test.go @@ -21,38 +21,6 @@ import ( virtualgrouptypes "github.com/bnb-chain/greenfield/x/virtualgroup/types" ) -func (s *PaymentTestSuite) copyObject(user keys.KeyManager, sp *core.StorageProvider, bucketName, objectName, dstBucketName, dstObjectName string) (*storagetypes.ObjectInfo, error) { - msgCopyObject := storagetypes.NewMsgCopyObject(user.GetAddr(), bucketName, dstBucketName, objectName, dstObjectName, math.MaxUint, nil) - msgCopyObject.DstPrimarySpApproval.Sig, _ = sp.ApprovalKey.Sign(msgCopyObject.GetApprovalBytes()) - - s.SendTxBlock(user, msgCopyObject) - // HeadObject - queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ - BucketName: dstBucketName, - ObjectName: dstObjectName, - } - headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) - return headObjectResponse.ObjectInfo, err - -} - -func (s *PaymentTestSuite) updateBucket(user keys.KeyManager, bucketName string, paymentAddress string, chargedReadQuota uint64) (*storagetypes.BucketInfo, error) { - - msgUpdateBucketInfo := storagetypes.NewMsgUpdateBucketInfo( - user.GetAddr(), bucketName, &chargedReadQuota, user.GetAddr(), storagetypes.VISIBILITY_TYPE_PRIVATE) - if paymentAddress != "" { - msgUpdateBucketInfo.PaymentAddress = paymentAddress - } - s.SendTxBlock(user, msgUpdateBucketInfo) - - queryHeadObjectRequest := storagetypes.QueryHeadBucketRequest{ - BucketName: bucketName, - } - headObjectResponse, err := s.Client.HeadBucket(context.Background(), &queryHeadObjectRequest) - return headObjectResponse.BucketInfo, err - -} - // TestStorageBill_CopyObject_WithoutPriceChange func (s *PaymentTestSuite) TestStorageBill_CopyObject_WithoutPriceChange() { var err error @@ -215,7 +183,7 @@ func (s *PaymentTestSuite) TestStorageBill_UpdateBucketQuota() { ctx := context.Background() sp := s.PickStorageProvider() // recover price - defer s.RecoverSPPrice(sp) + defer s.SetSPPrice(sp, "12.34", "0") gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -362,7 +330,7 @@ func (s *PaymentTestSuite) TestStorageBill_UpdatePaymentAddress() { var err error ctx := context.Background() sp := s.PickStorageProvider() - defer s.RecoverSPPrice(sp) + defer s.SetSPPrice(sp, "12.34", "0") gvg, found := sp.GetFirstGlobalVirtualGroup() s.Require().True(found) queryFamilyResponse, err := s.Client.GlobalVirtualGroupFamily(ctx, &virtualgrouptypes.QueryGlobalVirtualGroupFamilyRequest{ @@ -518,7 +486,7 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { var err error ctx := context.Background() primarySP := s.PickStorageProvider() - s.RecoverSPPrice(primarySP) + s.SetSPPrice(primarySP, "1", "1.15") gvg, found := primarySP.GetFirstGlobalVirtualGroup() s.Require().True(found) @@ -527,7 +495,7 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { }) s.Require().NoError(err) family := queryFamilyResponse.GlobalVirtualGroupFamily - user0 := s.GenAndChargeAccounts(1, 1000000)[0] + user0 := s.GenAndChargeAccounts(1, 10)[0] streamAddresses := []string{ user0.GetAddr().String(), @@ -536,6 +504,7 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { paymenttypes.ValidatorTaxPoolAddress.String(), } + streamAddresses0 := streamAddresses paymentParams, err := s.Client.PaymentQueryClient.Params(ctx, &paymenttypes.QueryParamsRequest{}) s.T().Logf("paymentParams %s, err: %v", paymentParams, err) s.Require().NoError(err) @@ -576,21 +545,8 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { taxRate0 := taxRate dstPrimarySP := s.CreateNewStorageProvider() - s.RecoverSPPrice(dstPrimarySP) - - // new sp CreateGlobalVirtualGroup - var secondarySPIDs []uint32 - var secondarySPs []*core.StorageProvider - - for _, ssp := range s.StorageProviders { - if ssp.Info.Id != primarySP.Info.Id { - secondarySPIDs = append(secondarySPIDs, ssp.Info.Id) - secondarySPs = append(secondarySPs, ssp) - } - if len(secondarySPIDs) == 6 { - break - } - } + s.SetSPPrice(dstPrimarySP, "2", "1.45") + _, secondarySPIDs := s.GetSecondarySP(dstPrimarySP, primarySP) gvgID, _ := s.BaseSuite.CreateGlobalVirtualGroup(dstPrimarySP, 0, secondarySPIDs, 1) gvgResp, err := s.Client.VirtualGroupQueryClient.GlobalVirtualGroup(context.Background(), &virtualgrouptypes.QueryGlobalVirtualGroupRequest{ GlobalVirtualGroupId: gvgID, @@ -611,41 +567,18 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { paymenttypes.ValidatorTaxPoolAddress.String(), } fundAddress := primarySP.FundingKey.GetAddr() - queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: fundAddress.String()} + streamRecordsBefore = s.getStreamRecords(streamAddresses) + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: fundAddress.String()} fundBalanceBefore, err := s.Client.BankQueryClient.Balance(context.Background(), &queryBalanceRequest) s.Require().NoError(err) - streamRecordsBefore = s.getStreamRecords(streamAddresses) - // construct the signatures - var gvgMappings []*storagetypes.GVGMapping - gvgMappings = append(gvgMappings, &storagetypes.GVGMapping{SrcGlobalVirtualGroupId: gvg.Id, DstGlobalVirtualGroupId: dstGVG.Id}) - for _, gvgMapping := range gvgMappings { - migrationBucketSignHash := storagetypes.NewSecondarySpMigrationBucketSignDoc(s.GetChainID(), bucketInfo.BucketInfo.Id, dstPrimarySP.Info.Id, gvgMapping.SrcGlobalVirtualGroupId, gvgMapping.DstGlobalVirtualGroupId).GetBlsSignHash() - secondarySigs := make([][]byte, 0) - secondarySPBlsPubKeys := make([]bls.PublicKey, 0) - for _, ssp := range secondarySPs { - sig, err := core.BlsSignAndVerify(ssp, migrationBucketSignHash) - s.Require().NoError(err) - secondarySigs = append(secondarySigs, sig) - pk, err := bls.PublicKeyFromBytes(ssp.BlsKey.PubKey().Bytes()) - s.Require().NoError(err) - secondarySPBlsPubKeys = append(secondarySPBlsPubKeys, pk) - } - aggBlsSig, err := core.BlsAggregateAndVerify(secondarySPBlsPubKeys, migrationBucketSignHash, secondarySigs) - s.Require().NoError(err) - gvgMapping.SecondarySpBlsSignature = aggBlsSig - } - - // send msgMigrationBucket - msgMigrationBucket := storagetypes.NewMsgMigrateBucket(user0.GetAddr(), bucketName, dstPrimarySP.Info.Id) - msgMigrationBucket.DstPrimarySpApproval.ExpiredHeight = math.MaxInt - msgMigrationBucket.DstPrimarySpApproval.Sig, err = dstPrimarySP.ApprovalKey.Sign(msgMigrationBucket.GetApprovalBytes()) + // MigrationBucket + msgMigrationBucket, msgCompleteMigrationBucket := s.NewMigrateBucket(primarySP, dstPrimarySP, user0, bucketName, gvg.FamilyId, dstGVG.FamilyId, bucketInfo.BucketInfo.Id) s.SendTxBlock(user0, msgMigrationBucket) s.Require().NoError(err) // complete MigrationBucket - msgCompleteMigrationBucket := storagetypes.NewMsgCompleteMigrateBucket(dstPrimarySP.OperatorKey.GetAddr(), bucketName, dstGVG.FamilyId, gvgMappings) s.SendTxBlock(dstPrimarySP.OperatorKey, msgCompleteMigrationBucket) streamRecordsAfter = s.getStreamRecords(streamAddresses) fundBalanceAfter, err := s.Client.BankQueryClient.Balance(context.Background(), &queryBalanceRequest) @@ -664,9 +597,100 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate.Sub(taxRate0)) s.Require().Equal(streamRecordsAfter.User.NetflowRate.Neg(), userTotalRate.Abs()) + s.SetSPPrice(primarySP, "12.3", "5000000000000000") + defer s.SetSPPrice(primarySP, "12.3", "5") + + queryBalanceRequest.Address = dstPrimarySP.FundingKey.GetAddr().String() + fundBalanceBefore, err = s.Client.BankQueryClient.Balance(context.Background(), &queryBalanceRequest) + s.Require().NoError(err) + streamRecordsBefore = s.getStreamRecords(streamAddresses0) + + // send msgMigrationBucket + msgMigrationBucket, msgCompleteMigrationBucket = s.NewMigrateBucket(dstPrimarySP, primarySP, user0, bucketName, dstGVG.FamilyId, gvg.FamilyId, bucketInfo.BucketInfo.Id) + + s.SendTxBlock(user0, msgMigrationBucket) + s.Require().NoError(err) + + s.SendTxBlockWithExpectErrorString(msgCompleteMigrationBucket, primarySP.OperatorKey, "apply stream record changes for user failed") + + s.SetSPPrice(primarySP, "12.3", "13") + readPrice, primaryPrice, secondaryPrice := s.getPrices(primarySP, time.Now().Unix()) + s.T().Logf("readPrice: %v, primaryPrice: %v,secondaryPrice: %v", readPrice, primaryPrice, secondaryPrice) + + s.SendTxBlock(primarySP.OperatorKey, msgCompleteMigrationBucket) + streamRecordsAfter = s.getStreamRecords(streamAddresses0) + fundBalanceAfter, err = s.Client.BankQueryClient.Balance(context.Background(), &queryBalanceRequest) + s.Require().NoError(err) + s.T().Logf("fundBalanceBefore: %v, fundBalanceAfter: %v, diff: %v", fundBalanceBefore, fundBalanceAfter, fundBalanceAfter.Balance.Amount.Sub(fundBalanceBefore.Balance.Amount)) + s.Require().True(fundBalanceAfter.Balance.Amount.Sub(fundBalanceBefore.Balance.Amount).GT(sdkmath.NewInt(0)), "migrate sp fund address need settle") + taxRate1 := taxRate + gvgFamilyRate, gvgRate, taxRate, userTotalRate = s.calculateStorageRates(primarySP, bucketName, objectName, payloadSize, time.Now().Unix()) + s.T().Logf("gvgFamilyRate: %v, gvgRate: %v, taxRate: %v, userTotalRate: %v", gvgFamilyRate, gvgRate, taxRate, userTotalRate) + s.T().Logf("NetflowRate: %v, userTotalRate: %v, actual taxRate diff: %v, expect taxRate diff: %v", streamRecordsAfter.User.NetflowRate.Neg(), userTotalRate.Neg(), streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate.Sub(taxRate0)) + + s.Require().Equal(streamRecordsAfter.User.StaticBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.User.LockBalance, sdkmath.ZeroInt()) + s.Require().Equal(streamRecordsAfter.GVGFamily.NetflowRate.Sub(streamRecordsBefore.GVGFamily.NetflowRate), gvgFamilyRate) + s.Require().Equal(streamRecordsAfter.GVG.NetflowRate.Sub(streamRecordsBefore.GVG.NetflowRate), gvgRate) + // tax rate diff + s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate.Sub(taxRate1)) + s.Require().Equal(streamRecordsAfter.User.NetflowRate.Neg(), userTotalRate.Abs()) +} + +func (s *PaymentTestSuite) 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 } +func (s *PaymentTestSuite) NewMigrateBucket(srcSP, dstSP *core.StorageProvider, user keys.KeyManager, bucketName string, srcID, dstID uint32, bucketID sdkmath.Uint) (*storagetypes.MsgMigrateBucket, *storagetypes.MsgCompleteMigrateBucket) { + + secondarySPs, _ := s.GetSecondarySP(srcSP, dstSP) + var gvgMappings []*storagetypes.GVGMapping + gvgMappings = append(gvgMappings, &storagetypes.GVGMapping{SrcGlobalVirtualGroupId: srcID, DstGlobalVirtualGroupId: dstID}) + for _, gvgMapping := range gvgMappings { + migrationBucketSignHash := storagetypes.NewSecondarySpMigrationBucketSignDoc(s.GetChainID(), bucketID, dstSP.Info.Id, gvgMapping.SrcGlobalVirtualGroupId, gvgMapping.DstGlobalVirtualGroupId).GetBlsSignHash() + secondarySigs := make([][]byte, 0) + secondarySPBlsPubKeys := make([]bls.PublicKey, 0) + for _, ssp := range secondarySPs { + sig, err := core.BlsSignAndVerify(ssp, migrationBucketSignHash) + s.Require().NoError(err) + secondarySigs = append(secondarySigs, sig) + pk, err := bls.PublicKeyFromBytes(ssp.BlsKey.PubKey().Bytes()) + s.Require().NoError(err) + secondarySPBlsPubKeys = append(secondarySPBlsPubKeys, pk) + } + aggBlsSig, err := core.BlsAggregateAndVerify(secondarySPBlsPubKeys, migrationBucketSignHash, secondarySigs) + s.Require().NoError(err) + gvgMapping.SecondarySpBlsSignature = aggBlsSig + } -func (s *PaymentTestSuite) RecoverSPPrice(sp *core.StorageProvider) { + msgMigrationBucket := storagetypes.NewMsgMigrateBucket(user.GetAddr(), bucketName, dstSP.Info.Id) + msgMigrationBucket.DstPrimarySpApproval.ExpiredHeight = math.MaxInt + msgMigrationBucket.DstPrimarySpApproval.Sig, _ = dstSP.ApprovalKey.Sign(msgMigrationBucket.GetApprovalBytes()) + + msgCompleteMigrationBucket := storagetypes.NewMsgCompleteMigrateBucket(dstSP.OperatorKey.GetAddr(), bucketName, dstID, gvgMappings) + + return msgMigrationBucket, msgCompleteMigrationBucket + +} +func (s *PaymentTestSuite) SetSPPrice(sp *core.StorageProvider, readPrice, storePrice string) { ctx := context.Background() queryGetSpStoragePriceByTimeResp, err := s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ @@ -674,14 +698,19 @@ func (s *PaymentTestSuite) RecoverSPPrice(sp *core.StorageProvider) { Timestamp: time.Now().Unix(), }) s.Require().NoError(err) - recoverReadPrice, err := sdk.NewDecFromStr("100.0087") + ReadPrice, err := sdk.NewDecFromStr(readPrice) s.Require().NoError(err) + StorePrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.StorePrice + if storePrice != "0" { + StorePrice, err = sdk.NewDecFromStr(storePrice) + s.Require().NoError(err) + } msgUpdatePrice := &sptypes.MsgUpdateSpStoragePrice{ SpAddress: sp.OperatorKey.GetAddr().String(), - ReadPrice: recoverReadPrice, + ReadPrice: ReadPrice, FreeReadQuota: queryGetSpStoragePriceByTimeResp.SpStoragePrice.FreeReadQuota, - StorePrice: queryGetSpStoragePriceByTimeResp.SpStoragePrice.StorePrice, + StorePrice: StorePrice, } s.SendTxBlock(sp.OperatorKey, msgUpdatePrice) queryGetSpStoragePriceByTimeResp, err = s.Client.QueryGetSpStoragePriceByTime(ctx, &sptypes.QueryGetSpStoragePriceByTimeRequest{ @@ -689,7 +718,8 @@ func (s *PaymentTestSuite) RecoverSPPrice(sp *core.StorageProvider) { Timestamp: time.Now().Unix(), }) s.Require().NoError(err) - s.T().Logf("queryGetSpStoragePriceByTimeResp read price: %s", queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice) + s.T().Logf("queryGetSpStoragePriceByTimeResp read price: %s, store price: %v", readPrice, storePrice) + } // CreatePaymentAccount create new payment account and return latest payment account @@ -715,3 +745,35 @@ func (s *PaymentTestSuite) CreatePaymentAccount(user keys.KeyManager, amount, de return paymentAccountAddr } + +func (s *PaymentTestSuite) copyObject(user keys.KeyManager, sp *core.StorageProvider, bucketName, objectName, dstBucketName, dstObjectName string) (*storagetypes.ObjectInfo, error) { + msgCopyObject := storagetypes.NewMsgCopyObject(user.GetAddr(), bucketName, dstBucketName, objectName, dstObjectName, math.MaxUint, nil) + msgCopyObject.DstPrimarySpApproval.Sig, _ = sp.ApprovalKey.Sign(msgCopyObject.GetApprovalBytes()) + + s.SendTxBlock(user, msgCopyObject) + // HeadObject + queryHeadObjectRequest := storagetypes.QueryHeadObjectRequest{ + BucketName: dstBucketName, + ObjectName: dstObjectName, + } + headObjectResponse, err := s.Client.HeadObject(context.Background(), &queryHeadObjectRequest) + return headObjectResponse.ObjectInfo, err + +} + +func (s *PaymentTestSuite) updateBucket(user keys.KeyManager, bucketName string, paymentAddress string, chargedReadQuota uint64) (*storagetypes.BucketInfo, error) { + + msgUpdateBucketInfo := storagetypes.NewMsgUpdateBucketInfo( + user.GetAddr(), bucketName, &chargedReadQuota, user.GetAddr(), storagetypes.VISIBILITY_TYPE_PRIVATE) + if paymentAddress != "" { + msgUpdateBucketInfo.PaymentAddress = paymentAddress + } + s.SendTxBlock(user, msgUpdateBucketInfo) + + queryHeadObjectRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + headObjectResponse, err := s.Client.HeadBucket(context.Background(), &queryHeadObjectRequest) + return headObjectResponse.BucketInfo, err + +} From 3aab41a9a07353a652c4fb56301c95e41e6748f0 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Fri, 21 Jul 2023 11:37:02 +0800 Subject: [PATCH 29/33] fix some review comments --- app/reconciliation.go | 3 ++- e2e/tests/payment_test.go | 2 -- e2e/tests/storage_bill_test.go | 3 ++- x/storage/keeper/grpc_query.go | 14 +++++++------- x/storage/keeper/payment.go | 16 +++++++--------- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/app/reconciliation.go b/app/reconciliation.go index 8043ec7b9..f6f2d34a2 100644 --- a/app/reconciliation.go +++ b/app/reconciliation.go @@ -126,7 +126,7 @@ func (app *App) reconPaymentChanges(ctx sdk.Context, paymentIavl *iavl.Store) bo ctx.Logger().Error("fail to unmarshal stream record", "err", err.Error()) } else { flowCurrent = flowCurrent.Add(sr.NetflowRate) - + //TODO: impact performance, remove it later j, _ := json.Marshal(sr) ctx.Logger().Debug("stream_record_current", "stream record", j, "addr", parseAddressFromStreamRecordKey(kBz)) } @@ -144,6 +144,7 @@ func (app *App) reconPaymentChanges(ctx sdk.Context, paymentIavl *iavl.Store) bo ctx.Logger().Error("fail to unmarshal stream record", "err", err.Error()) } else { flowPre = flowPre.Add(sr.NetflowRate) + //TODO: impact performance, remove it later j, _ := json.Marshal(sr) ctx.Logger().Debug("stream_record_previous", "stream record", j, "addr", parseAddressFromStreamRecordKey(kBz)) } diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 17133e33c..9d6e9fd61 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -926,8 +926,6 @@ func (s *PaymentTestSuite) TestWithdraw() { s.Require().Equal(paymentAccountStreamRecord.StaticBalance.Sub(paymentAccountStreamRecordAfter.StaticBalance).Int64(), amount.Add(staticBalanceChange).Int64()) } -func (s *PaymentTestSuite) TestWithdraw_WithoutEnoughBalance() {} - func (s *PaymentTestSuite) TestStorageBill_DeleteBucket_WithReadQuota() { var err error ctx := context.Background() diff --git a/e2e/tests/storage_bill_test.go b/e2e/tests/storage_bill_test.go index 3f63fe363..1e483b6c4 100644 --- a/e2e/tests/storage_bill_test.go +++ b/e2e/tests/storage_bill_test.go @@ -718,7 +718,8 @@ func (s *PaymentTestSuite) SetSPPrice(sp *core.StorageProvider, readPrice, store Timestamp: time.Now().Unix(), }) s.Require().NoError(err) - s.T().Logf("queryGetSpStoragePriceByTimeResp read price: %s, store price: %v", readPrice, storePrice) + s.T().Logf("queryGetSpStoragePriceByTimeResp read price: %s, store price: %v", + queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice, queryGetSpStoragePriceByTimeResp.SpStoragePrice.StorePrice) } diff --git a/x/storage/keeper/grpc_query.go b/x/storage/keeper/grpc_query.go index 2570efd89..ddcc0e4dd 100644 --- a/x/storage/keeper/grpc_query.go +++ b/x/storage/keeper/grpc_query.go @@ -101,20 +101,20 @@ func (k Keeper) QueryIsPriceChanged(c context.Context, req *types.QueryIsPriceCh primarySp := k.MustGetPrimarySPForBucket(ctx, bucketInfo) internalBucketInfo := k.MustGetInternalBucketInfo(ctx, bucketInfo.Id) - changed, currentRead, currentPrimary, currentSecondary, currentTaxRate, newRead, newPrimary, newSecondary, newTaxRate, err := k.IsPriceChanged(ctx, primarySp.Id, internalBucketInfo.PriceTime) + changed, currentPrice, currentTaxRate, newPrice, newTaxRate, err := k.IsPriceChanged(ctx, primarySp.Id, internalBucketInfo.PriceTime) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } return &types.QueryIsPriceChangedResponse{ Changed: changed, - CurrentReadPrice: currentRead, - CurrentPrimaryStorePrice: currentPrimary, - CurrentSecondaryStorePrice: currentSecondary, + CurrentReadPrice: currentPrice.ReadPrice, + CurrentPrimaryStorePrice: currentPrice.PrimaryStorePrice, + CurrentSecondaryStorePrice: currentPrice.ReadPrice, CurrentValidatorTaxRate: currentTaxRate, - NewReadPrice: newRead, - NewPrimaryStorePrice: newPrimary, - NewSecondaryStorePrice: newSecondary, + NewReadPrice: newPrice.ReadPrice, + NewPrimaryStorePrice: newPrice.PrimaryStorePrice, + NewSecondaryStorePrice: newPrice.SecondaryStorePrice, NewValidatorTaxRate: newTaxRate, }, nil } diff --git a/x/storage/keeper/payment.go b/x/storage/keeper/payment.go index abfee9faf..789682df9 100644 --- a/x/storage/keeper/payment.go +++ b/x/storage/keeper/payment.go @@ -160,39 +160,37 @@ func (k Keeper) UnlockAndChargeObjectStoreFee(ctx sdk.Context, primarySpId uint3 return k.ChargeObjectStoreFee(ctx, primarySpId, bucketInfo, internalBucketInfo, objectInfo) } -func (k Keeper) IsPriceChanged(ctx sdk.Context, primarySpId uint32, priceTime int64) (bool, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, sdk.Dec, error) { +func (k Keeper) IsPriceChanged(ctx sdk.Context, primarySpId uint32, priceTime int64) (bool, *types.StoragePrice, sdk.Dec, *types.StoragePrice, sdk.Dec, error) { prePrice, err := k.paymentKeeper.GetStoragePrice(ctx, types.StoragePriceParams{ PrimarySp: primarySpId, PriceTime: priceTime, }) if err != nil { - return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), err + return false, nil, sdk.ZeroDec(), nil, sdk.ZeroDec(), err } currentPrice, err := k.paymentKeeper.GetStoragePrice(ctx, types.StoragePriceParams{ PrimarySp: primarySpId, PriceTime: ctx.BlockTime().Unix(), }) if err != nil { - return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), err + return false, nil, sdk.ZeroDec(), nil, sdk.ZeroDec(), err } preParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, priceTime) if err != nil { - return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), err + return false, nil, sdk.ZeroDec(), nil, sdk.ZeroDec(), err } currentParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, ctx.BlockTime().Unix()) if err != nil { - return false, sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), err + return false, nil, sdk.ZeroDec(), nil, sdk.ZeroDec(), err } return !(prePrice.ReadPrice.Equal(currentPrice.ReadPrice) && prePrice.PrimaryStorePrice.Equal(currentPrice.PrimaryStorePrice) && prePrice.SecondaryStorePrice.Equal(currentPrice.SecondaryStorePrice) && preParams.ValidatorTaxRate.Equal(currentParams.ValidatorTaxRate)), - prePrice.ReadPrice, prePrice.PrimaryStorePrice, prePrice.SecondaryStorePrice, preParams.ValidatorTaxRate, - currentPrice.ReadPrice, currentPrice.PrimaryStorePrice, currentPrice.SecondaryStorePrice, currentParams.ValidatorTaxRate, - nil + &prePrice, preParams.ValidatorTaxRate, ¤tPrice, currentParams.ValidatorTaxRate, nil } func (k Keeper) ChargeObjectStoreFee(ctx sdk.Context, primarySpId uint32, bucketInfo *storagetypes.BucketInfo, @@ -202,7 +200,7 @@ func (k Keeper) ChargeObjectStoreFee(ctx sdk.Context, primarySpId uint32, bucket return fmt.Errorf("get charge size error: %w", err) } - priceChanged, _, _, _, _, _, _, _, _, err := k.IsPriceChanged(ctx, primarySpId, internalBucketInfo.PriceTime) + priceChanged, _, _, _, _, err := k.IsPriceChanged(ctx, primarySpId, internalBucketInfo.PriceTime) if err != nil { return fmt.Errorf("check whether price changed error: %w", err) } From ce9eb18c4146295efa5e09a083b894fed1dae68a Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Fri, 21 Jul 2023 11:45:04 +0800 Subject: [PATCH 30/33] fix some review comments --- x/payment/keeper/storage_fee_charge.go | 161 +++++++++++++------------ 1 file changed, 85 insertions(+), 76 deletions(-) diff --git a/x/payment/keeper/storage_fee_charge.go b/x/payment/keeper/storage_fee_charge.go index 0b97706c1..b8858c573 100644 --- a/x/payment/keeper/storage_fee_charge.go +++ b/x/payment/keeper/storage_fee_charge.go @@ -60,86 +60,95 @@ func (k Keeper) ApplyUserFlowsList(ctx sdk.Context, userFlowsList []types.UserFl streamRecord = types.NewStreamRecord(from, currentTime) } if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE { - var rateChanges []types.StreamRecordChange - totalRate := sdk.ZeroInt() - for _, flowChange := range userFlows.Flows { - rateChanges = append(rateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithRateChange(flowChange.Rate)) - totalRate = totalRate.Add(flowChange.Rate) - } - streamRecordChange := types.NewDefaultStreamRecordChangeWithAddr(from).WithRateChange(totalRate.Neg()) - // storage fee preview - if ctx.IsCheckTx() { - reserveTime := k.GetParams(ctx).VersionedParams.ReserveTime - changeRate := totalRate.Neg() - event := &types.EventFeePreview{ - Account: from.String(), - Amount: changeRate.Mul(sdkmath.NewIntFromUint64(reserveTime)).Abs(), - } - if changeRate.IsPositive() { - event.FeePreviewType = types.FEE_PREVIEW_TYPE_UNLOCKED_FEE - } else { - event.FeePreviewType = types.FEE_PREVIEW_TYPE_PRELOCKED_FEE - } - _ = ctx.EventManager().EmitTypedEvents(event) - } - err = k.UpdateStreamRecord(ctx, streamRecord, streamRecordChange) - if err != nil { - return fmt.Errorf("apply stream record changes for user failed: %w", err) - } - - // update flows - deltaFlowCount := k.MergeActiveOutFlows(ctx, from, userFlows.Flows) // deltaFlowCount can be negative - streamRecord.OutFlowCount = uint64(int64(streamRecord.OutFlowCount) + int64(deltaFlowCount)) - - k.SetStreamRecord(ctx, streamRecord) - err = k.ApplyStreamRecordChanges(ctx, rateChanges) - if err != nil { - return fmt.Errorf("apply stream record changes failed: %w", err) - } + return k.applyActiveUerFlows(ctx, userFlows, from, streamRecord) } else { // frozen status, should be called in end block for stop serving - forced, _ := ctx.Value(types.ForceUpdateStreamRecordKey).(bool) - if !forced { - return fmt.Errorf("stream record %s is frozen", streamRecord.Account) - } - - // the stream record could be totally frozen, or in the process of resuming - var activeOutFlows, frozenOutFlows []types.OutFlow - var activeRateChanges []types.StreamRecordChange - //var frozenRateChanges []types.StreamRecordChange - totalActiveRate, totalFrozenRate := sdk.ZeroInt(), sdk.ZeroInt() - for _, flowChange := range userFlows.Flows { - outFlow := k.GetOutFlow(ctx, sdk.MustAccAddressFromHex(streamRecord.Account), types.OUT_FLOW_STATUS_FROZEN, sdk.MustAccAddressFromHex(flowChange.ToAddress)) - if outFlow != nil { - frozenOutFlows = append(frozenOutFlows, flowChange) - //frozenRateChanges = append(frozenRateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithFrozenRateChange(flowChange.Rate)) - totalFrozenRate = totalFrozenRate.Add(flowChange.Rate) - } else { - activeOutFlows = append(activeOutFlows, flowChange) - activeRateChanges = append(activeRateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithRateChange(flowChange.Rate)) - totalActiveRate = totalActiveRate.Add(flowChange.Rate) - } - } - streamRecordChange := types.NewDefaultStreamRecordChangeWithAddr(from). - WithRateChange(totalActiveRate.Neg()).WithFrozenRateChange(totalFrozenRate.Neg()) - err = k.UpdateFrozenStreamRecord(ctx, streamRecord, streamRecordChange) - if err != nil { - return fmt.Errorf("apply stream record changes for user failed: %w", err) - } - - // update flows - deltaActiveFlowCount := k.MergeActiveOutFlows(ctx, from, activeOutFlows) // can be negative - deltaFrozenFlowCount := k.MergeFrozenOutFlows(ctx, from, frozenOutFlows) // can be negative - streamRecord.OutFlowCount = uint64(int64(streamRecord.OutFlowCount) + int64(deltaActiveFlowCount) + int64(deltaFrozenFlowCount)) - - k.SetStreamRecord(ctx, streamRecord) - //only apply activeRateChanges, for frozen rate changes, the out flow to gvg & gvg family had been deducted when settling - err = k.ApplyStreamRecordChanges(ctx, activeRateChanges) - if err != nil { - return fmt.Errorf("apply stream record changes failed: %w", err) - } + return k.applyFrozenUserFlows(ctx, userFlows, from, streamRecord) } } + return nil +} + +func (k Keeper) applyActiveUerFlows(ctx sdk.Context, userFlows types.UserFlows, from sdk.AccAddress, streamRecord *types.StreamRecord) error { + var rateChanges []types.StreamRecordChange + totalRate := sdk.ZeroInt() + for _, flowChange := range userFlows.Flows { + rateChanges = append(rateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithRateChange(flowChange.Rate)) + totalRate = totalRate.Add(flowChange.Rate) + } + streamRecordChange := types.NewDefaultStreamRecordChangeWithAddr(from).WithRateChange(totalRate.Neg()) + // storage fee preview + if ctx.IsCheckTx() { + reserveTime := k.GetParams(ctx).VersionedParams.ReserveTime + changeRate := totalRate.Neg() + event := &types.EventFeePreview{ + Account: from.String(), + Amount: changeRate.Mul(sdkmath.NewIntFromUint64(reserveTime)).Abs(), + } + if changeRate.IsPositive() { + event.FeePreviewType = types.FEE_PREVIEW_TYPE_UNLOCKED_FEE + } else { + event.FeePreviewType = types.FEE_PREVIEW_TYPE_PRELOCKED_FEE + } + _ = ctx.EventManager().EmitTypedEvents(event) + } + err := k.UpdateStreamRecord(ctx, streamRecord, streamRecordChange) + if err != nil { + return fmt.Errorf("apply stream record changes for user failed: %w", err) + } + // update flows + deltaFlowCount := k.MergeActiveOutFlows(ctx, from, userFlows.Flows) // deltaFlowCount can be negative + streamRecord.OutFlowCount = uint64(int64(streamRecord.OutFlowCount) + int64(deltaFlowCount)) + + k.SetStreamRecord(ctx, streamRecord) + err = k.ApplyStreamRecordChanges(ctx, rateChanges) + if err != nil { + return fmt.Errorf("apply stream record changes failed: %w", err) + } + return nil +} + +func (k Keeper) applyFrozenUserFlows(ctx sdk.Context, userFlows types.UserFlows, from sdk.AccAddress, streamRecord *types.StreamRecord) error { + forced, _ := ctx.Value(types.ForceUpdateStreamRecordKey).(bool) + if !forced { + return fmt.Errorf("stream record %s is frozen", streamRecord.Account) + } + + // the stream record could be totally frozen, or in the process of resuming + var activeOutFlows, frozenOutFlows []types.OutFlow + var activeRateChanges []types.StreamRecordChange + //var frozenRateChanges []types.StreamRecordChange + totalActiveRate, totalFrozenRate := sdk.ZeroInt(), sdk.ZeroInt() + for _, flowChange := range userFlows.Flows { + outFlow := k.GetOutFlow(ctx, sdk.MustAccAddressFromHex(streamRecord.Account), types.OUT_FLOW_STATUS_FROZEN, sdk.MustAccAddressFromHex(flowChange.ToAddress)) + if outFlow != nil { + frozenOutFlows = append(frozenOutFlows, flowChange) + //frozenRateChanges = append(frozenRateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithFrozenRateChange(flowChange.Rate)) + totalFrozenRate = totalFrozenRate.Add(flowChange.Rate) + } else { + activeOutFlows = append(activeOutFlows, flowChange) + activeRateChanges = append(activeRateChanges, *types.NewDefaultStreamRecordChangeWithAddr(sdk.MustAccAddressFromHex(flowChange.ToAddress)).WithRateChange(flowChange.Rate)) + totalActiveRate = totalActiveRate.Add(flowChange.Rate) + } + } + streamRecordChange := types.NewDefaultStreamRecordChangeWithAddr(from). + WithRateChange(totalActiveRate.Neg()).WithFrozenRateChange(totalFrozenRate.Neg()) + err := k.UpdateFrozenStreamRecord(ctx, streamRecord, streamRecordChange) + if err != nil { + return fmt.Errorf("apply stream record changes for user failed: %w", err) + } + + // update flows + deltaActiveFlowCount := k.MergeActiveOutFlows(ctx, from, activeOutFlows) // can be negative + deltaFrozenFlowCount := k.MergeFrozenOutFlows(ctx, from, frozenOutFlows) // can be negative + streamRecord.OutFlowCount = uint64(int64(streamRecord.OutFlowCount) + int64(deltaActiveFlowCount) + int64(deltaFrozenFlowCount)) + + k.SetStreamRecord(ctx, streamRecord) + //only apply activeRateChanges, for frozen rate changes, the out flow to gvg & gvg family had been deducted when settling + err = k.ApplyStreamRecordChanges(ctx, activeRateChanges) + if err != nil { + return fmt.Errorf("apply stream record changes failed: %w", err) + } return nil } From 90924e17325982b9bf4e3d22ec29394ca2d989b6 Mon Sep 17 00:00:00 2001 From: mocky-b Date: Fri, 21 Jul 2023 12:28:09 +0800 Subject: [PATCH 31/33] 1. use transfer BNB with TestStorageBill_MigrationBucket assertion --- e2e/core/basesuite.go | 6 +----- e2e/tests/storage_bill_test.go | 39 +++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/e2e/core/basesuite.go b/e2e/core/basesuite.go index d0db71175..3214fb6be 100644 --- a/e2e/core/basesuite.go +++ b/e2e/core/basesuite.go @@ -155,7 +155,7 @@ func (s *BaseSuite) SendTxBlock(from keys.KeyManager, msg ...sdk.Msg) *sdk.TxRes }) s.Require().NoError(err) - s.T().Logf("block_height: %d, tx_hash: 0x%s", getTxRes.TxResponse.Height, response.TxResponse.TxHash) + s.T().Logf("block_height: %d, tx_hash: 0x%s, GasUsed: %v", getTxRes.TxResponse.Height, response.TxResponse.TxHash, response.TxResponse.GasUsed) return getTxRes.TxResponse } @@ -358,10 +358,6 @@ func (sp *StorageProvider) GetFirstGlobalVirtualGroup() (*virtualgroupmoduletype } return nil, false } -func (sp *StorageProvider) UpdateSPPrice() (*virtualgroupmoduletypes.GlobalVirtualGroup, bool) { - - return nil, false -} func (s *BaseSuite) NewSpAcc() *StorageProvider { userAccs := s.GenAndChargeAccounts(5, 1000000) diff --git a/e2e/tests/storage_bill_test.go b/e2e/tests/storage_bill_test.go index 1e483b6c4..4f063ebb3 100644 --- a/e2e/tests/storage_bill_test.go +++ b/e2e/tests/storage_bill_test.go @@ -597,19 +597,18 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { s.Require().Equal(streamRecordsAfter.Tax.NetflowRate.Sub(streamRecordsBefore.Tax.NetflowRate), taxRate.Sub(taxRate0)) s.Require().Equal(streamRecordsAfter.User.NetflowRate.Neg(), userTotalRate.Abs()) - s.SetSPPrice(primarySP, "12.3", "5000000000000000") - defer s.SetSPPrice(primarySP, "12.3", "5") + s.SetSPPrice(primarySP, "12.3", "100") queryBalanceRequest.Address = dstPrimarySP.FundingKey.GetAddr().String() fundBalanceBefore, err = s.Client.BankQueryClient.Balance(context.Background(), &queryBalanceRequest) s.Require().NoError(err) streamRecordsBefore = s.getStreamRecords(streamAddresses0) - // send msgMigrationBucket msgMigrationBucket, msgCompleteMigrationBucket = s.NewMigrateBucket(dstPrimarySP, primarySP, user0, bucketName, dstGVG.FamilyId, gvg.FamilyId, bucketInfo.BucketInfo.Id) s.SendTxBlock(user0, msgMigrationBucket) s.Require().NoError(err) + s.reduceBNBBalance(user0, s.Validator, sdkmath.NewIntWithDecimal(1, 1)) s.SendTxBlockWithExpectErrorString(msgCompleteMigrationBucket, primarySP.OperatorKey, "apply stream record changes for user failed") @@ -617,6 +616,8 @@ func (s *PaymentTestSuite) TestStorageBill_MigrationBucket() { readPrice, primaryPrice, secondaryPrice := s.getPrices(primarySP, time.Now().Unix()) s.T().Logf("readPrice: %v, primaryPrice: %v,secondaryPrice: %v", readPrice, primaryPrice, secondaryPrice) + s.transferBNB(s.Validator, user0, sdkmath.NewIntWithDecimal(10000, 18)) + s.SendTxBlock(primarySP.OperatorKey, msgCompleteMigrationBucket) streamRecordsAfter = s.getStreamRecords(streamAddresses0) fundBalanceAfter, err = s.Client.BankQueryClient.Balance(context.Background(), &queryBalanceRequest) @@ -778,3 +779,35 @@ func (s *PaymentTestSuite) updateBucket(user keys.KeyManager, bucketName string, return headObjectResponse.BucketInfo, err } + +func (s *PaymentTestSuite) reduceBNBBalance(user, to keys.KeyManager, leftBalance sdkmath.Int) { + queryBalanceRequest := banktypes.QueryBalanceRequest{Denom: s.Config.Denom, Address: user.GetAddr().String()} + queryBalanceResponse, err := s.Client.BankQueryClient.Balance(context.Background(), &queryBalanceRequest) + s.Require().NoError(err) + + msgSend := banktypes.NewMsgSend(user.GetAddr(), to.GetAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, queryBalanceResponse.Balance.Amount.SubRaw(5*types.DecimalGwei)), + )) + + simulateResponse := s.SimulateTx(msgSend, user) + gasLimit := simulateResponse.GasInfo.GetGasUsed() + gasPrice, err := sdk.ParseCoinNormalized(simulateResponse.GasInfo.GetMinGasPrice()) + s.Require().NoError(err) + sendBNBAmount := queryBalanceResponse.Balance.Amount.Sub(gasPrice.Amount.Mul(sdk.NewInt(int64(gasLimit)))).Sub(leftBalance) + msgSend.Amount = sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, sendBNBAmount), + ) + s.SendTxBlock(user, msgSend) + queryBalanceResponse, err = s.Client.BankQueryClient.Balance(context.Background(), &queryBalanceRequest) + s.Require().NoError(err) + s.T().Logf("balance: %v", queryBalanceResponse.Balance.Amount) +} + +func (s *PaymentTestSuite) transferBNB(user, to keys.KeyManager, amount sdkmath.Int) { + + msgSend := banktypes.NewMsgSend(user.GetAddr(), to.GetAddr(), sdk.NewCoins( + sdk.NewCoin(s.Config.Denom, amount), + )) + s.SendTxBlock(user, msgSend) + +} From 0674e49898258d82d45a9ebd1975a2929601283e Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Fri, 21 Jul 2023 17:13:15 +0800 Subject: [PATCH 32/33] fix an issue --- x/payment/keeper/storage_fee_charge.go | 10 ++++++++-- x/payment/types/stream_record.go | 1 + x/storage/keeper/payment.go | 1 - 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/x/payment/keeper/storage_fee_charge.go b/x/payment/keeper/storage_fee_charge.go index b8858c573..c5d3239df 100644 --- a/x/payment/keeper/storage_fee_charge.go +++ b/x/payment/keeper/storage_fee_charge.go @@ -60,9 +60,15 @@ func (k Keeper) ApplyUserFlowsList(ctx sdk.Context, userFlowsList []types.UserFl streamRecord = types.NewStreamRecord(from, currentTime) } if streamRecord.Status == types.STREAM_ACCOUNT_STATUS_ACTIVE { - return k.applyActiveUerFlows(ctx, userFlows, from, streamRecord) + err = k.applyActiveUerFlows(ctx, userFlows, from, streamRecord) + if err != nil { + return err + } } else { // frozen status, should be called in end block for stop serving - return k.applyFrozenUserFlows(ctx, userFlows, from, streamRecord) + err = k.applyFrozenUserFlows(ctx, userFlows, from, streamRecord) + if err != nil { + return err + } } } return nil diff --git a/x/payment/types/stream_record.go b/x/payment/types/stream_record.go index 22269dbf8..898d8b82a 100644 --- a/x/payment/types/stream_record.go +++ b/x/payment/types/stream_record.go @@ -13,5 +13,6 @@ func NewStreamRecord(account sdk.AccAddress, crudTimestamp int64) *StreamRecord BufferBalance: sdkmath.ZeroInt(), NetflowRate: sdkmath.ZeroInt(), LockBalance: sdkmath.ZeroInt(), + Status: STREAM_ACCOUNT_STATUS_ACTIVE, } } diff --git a/x/storage/keeper/payment.go b/x/storage/keeper/payment.go index 789682df9..7d324b9d9 100644 --- a/x/storage/keeper/payment.go +++ b/x/storage/keeper/payment.go @@ -347,7 +347,6 @@ func (k Keeper) ChargeViaBucketChange(ctx sdk.Context, bucketInfo *storagetypes. if err = changeFunc(bucketInfo, internalBucketInfo); err != nil { return errors.Wrapf(err, "change bucket internal info failed") } - // calculate new bill internalBucketInfo.PriceTime = ctx.BlockTime().Unix() newBill, err := k.GetBucketReadStoreBill(ctx, bucketInfo, internalBucketInfo) From 331e068a125df9105b15680815e2aa404bfaf0a1 Mon Sep 17 00:00:00 2001 From: forcodedancing Date: Fri, 21 Jul 2023 17:23:50 +0800 Subject: [PATCH 33/33] update swaggger --- swagger/static/swagger.yaml | 339 ++++++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) diff --git a/swagger/static/swagger.yaml b/swagger/static/swagger.yaml index f1e2a5a6a..8fd152810 100644 --- a/swagger/static/swagger.yaml +++ b/swagger/static/swagger.yaml @@ -2348,6 +2348,109 @@ paths: type: string tags: - Query + /greenfield/storage/head_bucket_extra/{bucket_name}: + get: + summary: >- + Queries a bucket extra info (with gvg bindings and price time) with + specify name. + operationId: HeadBucketExtra + responses: + '200': + description: A successful response. + schema: + type: object + properties: + extra_info: + type: object + properties: + price_time: + type: string + format: int64 + title: >- + the time of the payment price, used to calculate the + charge rate of the bucket + total_charge_size: + type: string + format: uint64 + title: >- + the total size of the objects in the bucket, used to + calculate the charge rate of the bucket + local_virtual_groups: + type: array + items: + type: object + properties: + id: + type: integer + format: int64 + description: id is the identifier of the local virtual group. + global_virtual_group_id: + type: integer + format: int64 + description: >- + global_virtual_group_id is the identifier of the + global virtual group. + stored_size: + type: string + format: uint64 + description: >- + stored_size is the size of the stored data in the + local virtual group. + total_charge_size: + type: string + format: uint64 + title: >- + total_charge_size is the total charged size of the + objects in the LVG. + + Notice that the minimum unit of charge is 128K + description: >- + Local virtual group(LVG) uniquely associated with a + global virtual group. + + Each bucket maintains a mapping from local virtual group + to global virtual group + + Each local virtual group is associated with a unique + virtual payment account, + + where all object fees are streamed to. + description: local_virtual_groups contains all the lvg of this bucket. + next_local_virtual_group_id: + type: integer + format: int64 + title: >- + next_local_virtual_group_id store the next id used by + local virtual group + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: bucket_name + in: path + required: true + type: string + tags: + - Query /greenfield/storage/head_bucket_nft/{token_id}: get: summary: Queries a bucket with EIP712 standard metadata info @@ -3041,6 +3144,63 @@ paths: type: string tags: - Query + /greenfield/storage/is_price_changed/{bucket_name}: + get: + summary: Queries whether read and storage prices changed for the bucket. + operationId: QueryIsPriceChanged + responses: + '200': + description: A successful response. + schema: + type: object + properties: + changed: + type: boolean + current_read_price: + type: string + current_primary_store_price: + type: string + current_secondary_store_price: + type: string + current_validator_tax_rate: + type: string + new_read_price: + type: string + new_primary_store_price: + type: string + new_secondary_store_price: + type: string + new_validator_tax_rate: + type: string + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: bucket_name + in: path + required: true + type: string + tags: + - Query /greenfield/storage/list_buckets: get: summary: Queries a list of bucket items. @@ -32860,6 +33020,99 @@ definitions: value: type: string title: attributes + greenfield.storage.InternalBucketInfo: + type: object + properties: + price_time: + type: string + format: int64 + title: >- + the time of the payment price, used to calculate the charge rate of + the bucket + total_charge_size: + type: string + format: uint64 + title: >- + the total size of the objects in the bucket, used to calculate the + charge rate of the bucket + local_virtual_groups: + type: array + items: + type: object + properties: + id: + type: integer + format: int64 + description: id is the identifier of the local virtual group. + global_virtual_group_id: + type: integer + format: int64 + description: >- + global_virtual_group_id is the identifier of the global virtual + group. + stored_size: + type: string + format: uint64 + description: >- + stored_size is the size of the stored data in the local virtual + group. + total_charge_size: + type: string + format: uint64 + title: >- + total_charge_size is the total charged size of the objects in + the LVG. + + Notice that the minimum unit of charge is 128K + description: >- + Local virtual group(LVG) uniquely associated with a global virtual + group. + + Each bucket maintains a mapping from local virtual group to global + virtual group + + Each local virtual group is associated with a unique virtual payment + account, + + where all object fees are streamed to. + description: local_virtual_groups contains all the lvg of this bucket. + next_local_virtual_group_id: + type: integer + format: int64 + title: >- + next_local_virtual_group_id store the next id used by local virtual + group + greenfield.storage.LocalVirtualGroup: + type: object + properties: + id: + type: integer + format: int64 + description: id is the identifier of the local virtual group. + global_virtual_group_id: + type: integer + format: int64 + description: global_virtual_group_id is the identifier of the global virtual group. + stored_size: + type: string + format: uint64 + description: stored_size is the size of the stored data in the local virtual group. + total_charge_size: + type: string + format: uint64 + title: |- + total_charge_size is the total charged size of the objects in the LVG. + Notice that the minimum unit of charge is 128K + description: >- + Local virtual group(LVG) uniquely associated with a global virtual group. + + Each bucket maintains a mapping from local virtual group to global virtual + group + + Each local virtual group is associated with a unique virtual payment + account, + + where all object fees are streamed to. greenfield.storage.ObjectInfo: type: object properties: @@ -33141,6 +33394,71 @@ definitions: value: type: string title: attributes + greenfield.storage.QueryHeadBucketExtraResponse: + type: object + properties: + extra_info: + type: object + properties: + price_time: + type: string + format: int64 + title: >- + the time of the payment price, used to calculate the charge rate + of the bucket + total_charge_size: + type: string + format: uint64 + title: >- + the total size of the objects in the bucket, used to calculate the + charge rate of the bucket + local_virtual_groups: + type: array + items: + type: object + properties: + id: + type: integer + format: int64 + description: id is the identifier of the local virtual group. + global_virtual_group_id: + type: integer + format: int64 + description: >- + global_virtual_group_id is the identifier of the global + virtual group. + stored_size: + type: string + format: uint64 + description: >- + stored_size is the size of the stored data in the local + virtual group. + total_charge_size: + type: string + format: uint64 + title: >- + total_charge_size is the total charged size of the objects + in the LVG. + + Notice that the minimum unit of charge is 128K + description: >- + Local virtual group(LVG) uniquely associated with a global + virtual group. + + Each bucket maintains a mapping from local virtual group to + global virtual group + + Each local virtual group is associated with a unique virtual + payment account, + + where all object fees are streamed to. + description: local_virtual_groups contains all the lvg of this bucket. + next_local_virtual_group_id: + type: integer + format: int64 + title: >- + next_local_virtual_group_id store the next id used by local + virtual group greenfield.storage.QueryHeadBucketResponse: type: object properties: @@ -33391,6 +33709,27 @@ definitions: objects of each bucket must be stored in a GVG within a group family. + greenfield.storage.QueryIsPriceChangedResponse: + type: object + properties: + changed: + type: boolean + current_read_price: + type: string + current_primary_store_price: + type: string + current_secondary_store_price: + type: string + current_validator_tax_rate: + type: string + new_read_price: + type: string + new_primary_store_price: + type: string + new_secondary_store_price: + type: string + new_validator_tax_rate: + type: string greenfield.storage.QueryListBucketsResponse: type: object properties: