diff --git a/e2e/tests/payment_test.go b/e2e/tests/payment_test.go index 1b8e8f453..035038041 100644 --- a/e2e/tests/payment_test.go +++ b/e2e/tests/payment_test.go @@ -1,13 +1,26 @@ package tests import ( + "bytes" "context" + "fmt" + "math" + "strconv" "testing" + "time" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" "github.com/stretchr/testify/suite" "github.com/bnb-chain/greenfield/e2e/core" + "github.com/bnb-chain/greenfield/sdk/keys" + "github.com/bnb-chain/greenfield/sdk/types" + storagetestutil "github.com/bnb-chain/greenfield/testutil/storage" paymenttypes "github.com/bnb-chain/greenfield/x/payment/types" + storagetypes "github.com/bnb-chain/greenfield/x/storage/types" ) type PaymentTestSuite struct { @@ -59,6 +72,199 @@ 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() + + 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) + proposalRes, err := s.Client.GovQueryClientV1.Proposal(ctx, queryProposal) + s.Require().NoError(err) + s.Require().Equal(proposalRes.Proposal.Status, govtypesv1.ProposalStatus_PROPOSAL_STATUS_PASSED) +} + +func (s *PaymentTestSuite) createObject() (keys.KeyManager, string, string, storagetypes.Uint, []byte) { + var err error + sp := s.StorageProviders[0] + // CreateBucket + user := s.GenAndChargeAccounts(1, 1000000)[0] + bucketName := "ch" + storagetestutil.GenRandomBucketName() + msgCreateBucket := storagetypes.NewMsgCreateBucket( + user.GetAddr(), bucketName, storagetypes.VISIBILITY_TYPE_PRIVATE, sp.OperatorKey.GetAddr(), + nil, math.MaxUint, nil, 10000) + msgCreateBucket.PrimarySpApproval.Sig, err = sp.ApprovalKey.Sign(msgCreateBucket.GetApprovalBytes()) + s.Require().NoError(err) + s.SendTxBlock(user, msgCreateBucket) + + // CreateObject + objectName := storagetestutil.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, 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, checksum +} + +func (s *PaymentTestSuite) sealObject(bucketName, objectName string, objectId storagetypes.Uint, checksum []byte) { + sp := s.StorageProviders[0] + + secondarySPs := []sdk.AccAddress{ + sp.OperatorKey.GetAddr(), sp.OperatorKey.GetAddr(), + sp.OperatorKey.GetAddr(), sp.OperatorKey.GetAddr(), + sp.OperatorKey.GetAddr(), sp.OperatorKey.GetAddr(), + } + msgSealObject := storagetypes.NewMsgSealObject(sp.SealKey.GetAddr(), bucketName, objectName, secondarySPs, nil) + sr := storagetypes.NewSecondarySpSignDoc(sp.OperatorKey.GetAddr(), objectId, checksum) + secondarySig, err := sp.ApprovalKey.Sign(sr.GetSignBytes()) + s.Require().NoError(err) + err = storagetypes.VerifySignature(sp.ApprovalKey.GetAddr(), sdk.Keccak256(sr.GetSignBytes()), secondarySig) + s.Require().NoError(err) + + secondarySigs := [][]byte{secondarySig, secondarySig, secondarySig, secondarySig, secondarySig, secondarySig} + msgSealObject.SecondarySpSignatures = secondarySigs + s.SendTxBlock(sp.SealKey, msgSealObject) + + 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) + s.Require().Equal(queryHeadObjectResponse.ObjectInfo.ObjectStatus, storagetypes.OBJECT_STATUS_SEALED) +} + +func (s *PaymentTestSuite) TestVersionedParams() { + ctx := context.Background() + queryParamsRequest := paymenttypes.QueryParamsRequest{} + queryParamsResponse, err := s.Client.PaymentQueryClient.Params(ctx, &queryParamsRequest) + s.Require().NoError(err) + + queryStreamRequest := paymenttypes.QueryGetStreamRecordRequest{Account: paymenttypes.ValidatorTaxPoolAddress.String()} + queryStreamResponse, err := s.Client.PaymentQueryClient.StreamRecord(ctx, &queryStreamRequest) + s.Require().NoError(err) + validatorTaxPoolRate := queryStreamResponse.StreamRecord.NetflowRate + s.T().Logf("netflow, validatorTaxPoolRate: %s", validatorTaxPoolRate) + + // create bucket, create object + user, bucketName, objectName, objectId, checksum := s.createObject() + + // update params + 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) + + // seal object + s.sealObject(bucketName, objectName, objectId, checksum) + + // delete object + msgDeleteObject := storagetypes.NewMsgDeleteObject(user.GetAddr(), bucketName, objectName) + s.SendTxBlock(user, msgDeleteObject) + + // delete bucket + msgDeleteBucket := storagetypes.NewMsgDeleteBucket(user.GetAddr(), bucketName) + s.SendTxBlock(user, msgDeleteBucket) + + 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.VersionedParams.ValidatorTaxRate = oldValidatorTaxRate + s.updateParams(params) +} + func TestPaymentTestSuite(t *testing.T) { suite.Run(t, new(PaymentTestSuite)) } diff --git a/e2e/tests/storage_test.go b/e2e/tests/storage_test.go index f07b56011..62294ca80 100644 --- a/e2e/tests/storage_test.go +++ b/e2e/tests/storage_test.go @@ -492,7 +492,7 @@ func (s *StorageTestSuite) TestPayment_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.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() + userTaxRate := paymentParams.Params.VersionedParams.ValidatorTaxRate.MulInt(readChargeRate).TruncateInt() userTotalRate := readChargeRate.Add(userTaxRate) s.Require().Equal(usr.NetflowRate.Abs(), userTotalRate) expectedOutFlows := []paymenttypes.OutFlow{ @@ -681,7 +681,7 @@ func (s *StorageTestSuite) TestPayment_AutoSettle() { s.Require().NoError(err) readPrice := queryGetSpStoragePriceByTimeResp.SpStoragePrice.ReadPrice totalUserRate := readPrice.MulInt(sdkmath.NewIntFromUint64(bucketChargedReadQuota)).TruncateInt() - taxRateParam := paymentParams.Params.ValidatorTaxRate + taxRateParam := paymentParams.Params.VersionedParams.ValidatorTaxRate taxStreamRate := taxRateParam.MulInt(totalUserRate).TruncateInt() expectedRate := totalUserRate.Add(taxStreamRate) paymentAccountBNBNeeded := expectedRate.Mul(sdkmath.NewIntFromUint64(reserveTime)) diff --git a/proto/greenfield/payment/params.proto b/proto/greenfield/payment/params.proto index 704c08e1b..9392301fc 100644 --- a/proto/greenfield/payment/params.proto +++ b/proto/greenfield/payment/params.proto @@ -18,16 +18,16 @@ message Params { uint64 max_auto_force_settle_num = 4 [(gogoproto.moretags) = "yaml:\"max_auto_force_settle_num\""]; // The denom of fee charged in payment module string fee_denom = 5 [(gogoproto.moretags) = "yaml:\"fee_denom\""]; - // The tax rate to pay for validators in storage payment. The default value is 1%(0.01) - string validator_tax_rate = 6 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; } // VersionedParams defines the parameters with multiple versions, each version is stored with different timestamp. message VersionedParams { // Time duration which the buffer balance need to be reserved for NetOutFlow e.g. 6 month uint64 reserve_time = 1 [(gogoproto.moretags) = "yaml:\"reserve_time\""]; + // The tax rate to pay for validators in storage payment. The default value is 1%(0.01) + string validator_tax_rate = 2 [ + (cosmos_proto.scalar) = "cosmos.Dec", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; } diff --git a/x/payment/types/params.go b/x/payment/types/params.go index 7b34126de..4a67fa1c6 100644 --- a/x/payment/types/params.go +++ b/x/payment/types/params.go @@ -17,12 +17,13 @@ var ( KeyFeeDenom = []byte("FeeDenom") KeyValidatorTaxRate = []byte("ValidatorTaxRate") - DefaultReserveTime uint64 = 180 * 24 * 60 * 60 // 180 days - DefaultForcedSettleTime uint64 = 24 * 60 * 60 // 1 day - DefaultPaymentAccountCountLimit uint64 = 200 - DefaultMaxAutoForceSettleNum uint64 = 100 - DefaultFeeDenom string = "BNB" - DefaultValidatorTaxRate sdk.Dec = sdk.NewDecWithPrec(1, 2) // 1% + DefaultReserveTime uint64 = 180 * 24 * 60 * 60 // 180 days + DefaultValidatorTaxRate sdk.Dec = sdk.NewDecWithPrec(1, 2) // 1% + + DefaultForcedSettleTime uint64 = 24 * 60 * 60 // 1 day + DefaultPaymentAccountCountLimit uint64 = 200 + DefaultMaxAutoForceSettleNum uint64 = 100 + DefaultFeeDenom string = "BNB" ) // ParamKeyTable the param key table for launch module @@ -33,19 +34,18 @@ func ParamKeyTable() paramtypes.KeyTable { // NewParams creates a new Params instance func NewParams( reserveTime uint64, + validatorTaxRate sdk.Dec, forcedSettleTime uint64, paymentAccountCountLimit uint64, maxAutoForceSettleNum uint64, feeDenom string, - validatorTaxRate sdk.Dec, ) Params { return Params{ - VersionedParams: VersionedParams{ReserveTime: reserveTime}, + VersionedParams: VersionedParams{ReserveTime: reserveTime, ValidatorTaxRate: validatorTaxRate}, ForcedSettleTime: forcedSettleTime, PaymentAccountCountLimit: paymentAccountCountLimit, MaxAutoForceSettleNum: maxAutoForceSettleNum, FeeDenom: feeDenom, - ValidatorTaxRate: validatorTaxRate, } } @@ -53,11 +53,11 @@ func NewParams( func DefaultParams() Params { return NewParams( DefaultReserveTime, + DefaultValidatorTaxRate, DefaultForcedSettleTime, DefaultPaymentAccountCountLimit, DefaultMaxAutoForceSettleNum, DefaultFeeDenom, - DefaultValidatorTaxRate, ) } @@ -65,11 +65,11 @@ func DefaultParams() Params { func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { return paramtypes.ParamSetPairs{ paramtypes.NewParamSetPair(KeyReserveTime, &p.VersionedParams.ReserveTime, validateReserveTime), + paramtypes.NewParamSetPair(KeyValidatorTaxRate, &p.VersionedParams.ValidatorTaxRate, validateValidatorTaxRate), paramtypes.NewParamSetPair(KeyForcedSettleTime, &p.ForcedSettleTime, validateForcedSettleTime), paramtypes.NewParamSetPair(KeyPaymentAccountCountLimit, &p.PaymentAccountCountLimit, validatePaymentAccountCountLimit), paramtypes.NewParamSetPair(KeyMaxAutoForceSettleNum, &p.MaxAutoForceSettleNum, validateMaxAutoForceSettleNum), paramtypes.NewParamSetPair(KeyFeeDenom, &p.FeeDenom, validateFeeDenom), - paramtypes.NewParamSetPair(KeyValidatorTaxRate, &p.ValidatorTaxRate, validateValidatorTaxRate), } } @@ -79,6 +79,10 @@ func (p Params) Validate() error { return err } + if err := validateValidatorTaxRate(p.VersionedParams.ValidatorTaxRate); err != nil { + return err + } + if err := validateForcedSettleTime(p.ForcedSettleTime); err != nil { return err } @@ -95,9 +99,6 @@ func (p Params) Validate() error { return err } - if err := validateValidatorTaxRate(p.ValidatorTaxRate); err != nil { - return err - } return nil } diff --git a/x/payment/types/params.pb.go b/x/payment/types/params.pb.go index 1fb8bc139..cd37e93ad 100644 --- a/x/payment/types/params.pb.go +++ b/x/payment/types/params.pb.go @@ -37,8 +37,6 @@ type Params struct { MaxAutoForceSettleNum uint64 `protobuf:"varint,4,opt,name=max_auto_force_settle_num,json=maxAutoForceSettleNum,proto3" json:"max_auto_force_settle_num,omitempty" yaml:"max_auto_force_settle_num"` // The denom of fee charged in payment module FeeDenom string `protobuf:"bytes,5,opt,name=fee_denom,json=feeDenom,proto3" json:"fee_denom,omitempty" yaml:"fee_denom"` - // The tax rate to pay for validators in storage payment. The default value is 1%(0.01) - ValidatorTaxRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=validator_tax_rate,json=validatorTaxRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"validator_tax_rate"` } func (m *Params) Reset() { *m = Params{} } @@ -113,6 +111,8 @@ func (m *Params) GetFeeDenom() string { type VersionedParams struct { // Time duration which the buffer balance need to be reserved for NetOutFlow e.g. 6 month ReserveTime uint64 `protobuf:"varint,1,opt,name=reserve_time,json=reserveTime,proto3" json:"reserve_time,omitempty" yaml:"reserve_time"` + // The tax rate to pay for validators in storage payment. The default value is 1%(0.01) + ValidatorTaxRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=validator_tax_rate,json=validatorTaxRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"validator_tax_rate"` } func (m *VersionedParams) Reset() { *m = VersionedParams{} } @@ -163,38 +163,38 @@ func init() { func init() { proto.RegisterFile("greenfield/payment/params.proto", fileDescriptor_bd7d37632356c8f4) } var fileDescriptor_bd7d37632356c8f4 = []byte{ - // 489 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xcd, 0x6e, 0xd3, 0x4c, - 0x14, 0x8d, 0xbf, 0x2f, 0x44, 0x74, 0x8a, 0xd4, 0x68, 0x28, 0xc2, 0x29, 0xc2, 0x8e, 0x0c, 0xaa, - 0xb2, 0x89, 0x2d, 0x60, 0x57, 0xb1, 0x69, 0x88, 0x90, 0x10, 0x3f, 0x42, 0x26, 0x62, 0xc1, 0x82, - 0xd1, 0xc4, 0xbe, 0x49, 0x0d, 0x1e, 0x4f, 0x34, 0x1e, 0x47, 0xce, 0x5b, 0xc0, 0xbb, 0xf0, 0x10, - 0x5d, 0x56, 0xac, 0x10, 0x0b, 0x0b, 0x25, 0x6f, 0xe0, 0x27, 0x40, 0x9e, 0x99, 0x94, 0x40, 0x05, - 0x9b, 0xf9, 0x39, 0xe7, 0xdc, 0x73, 0xaf, 0xee, 0xbd, 0xc8, 0x9d, 0x0b, 0x80, 0x6c, 0x96, 0x40, - 0x1a, 0x07, 0x0b, 0xba, 0x62, 0x90, 0xc9, 0x60, 0x41, 0x05, 0x65, 0xb9, 0xbf, 0x10, 0x5c, 0x72, - 0x8c, 0x7f, 0x09, 0x7c, 0x23, 0x38, 0xea, 0x45, 0x3c, 0x67, 0x3c, 0x27, 0x4a, 0x11, 0xe8, 0x8f, - 0x96, 0x1f, 0x1d, 0xce, 0xf9, 0x9c, 0x6b, 0xbc, 0x79, 0x69, 0xd4, 0xfb, 0xdc, 0x46, 0x9d, 0xd7, - 0xca, 0x15, 0x4f, 0x50, 0x77, 0x09, 0x22, 0x4f, 0x78, 0x06, 0x31, 0xd1, 0x99, 0x6c, 0xab, 0x6f, - 0x0d, 0xf6, 0x1f, 0xde, 0xf3, 0xaf, 0xa6, 0xf2, 0xdf, 0x6e, 0xb5, 0x3a, 0x7c, 0xd4, 0x3e, 0xaf, - 0xdc, 0x56, 0x78, 0xb0, 0xfc, 0x1d, 0xc6, 0x80, 0xee, 0x98, 0x08, 0x42, 0xa3, 0x88, 0x17, 0x99, - 0x24, 0xfa, 0x4c, 0x13, 0x96, 0x48, 0xfb, 0xbf, 0xbe, 0x35, 0x68, 0x8f, 0x8e, 0xeb, 0xca, 0xf5, - 0x56, 0x94, 0xa5, 0x27, 0xde, 0x3f, 0xc4, 0x5e, 0x68, 0x1b, 0xf6, 0x54, 0x93, 0x4f, 0x9a, 0xe3, - 0x45, 0x43, 0xe1, 0xe7, 0x08, 0xcf, 0xb8, 0x88, 0x20, 0x26, 0x39, 0x48, 0x99, 0x02, 0x91, 0x09, - 0x03, 0xfb, 0x7f, 0xe5, 0x7e, 0xb7, 0xae, 0xdc, 0x9e, 0x76, 0xbf, 0xaa, 0xf1, 0xc2, 0xae, 0x06, - 0xdf, 0x28, 0x6c, 0x92, 0x30, 0xc0, 0xef, 0x51, 0x8f, 0xd1, 0x92, 0xd0, 0x42, 0x72, 0xa2, 0xc8, - 0x6d, 0x40, 0x56, 0x30, 0xbb, 0xad, 0x3c, 0xef, 0xd7, 0x95, 0xdb, 0xd7, 0x9e, 0x7f, 0x95, 0x7a, - 0xe1, 0x2d, 0x46, 0xcb, 0xd3, 0x42, 0xf2, 0xa7, 0x0d, 0xa3, 0x13, 0xbc, 0x2a, 0x18, 0x7e, 0x80, - 0xf6, 0x66, 0x00, 0x24, 0x86, 0x8c, 0x33, 0xfb, 0x5a, 0xdf, 0x1a, 0xec, 0x8d, 0x0e, 0xeb, 0xca, - 0xed, 0x9a, 0x1a, 0xb7, 0x94, 0x17, 0x5e, 0x9f, 0x01, 0x8c, 0x9b, 0x27, 0xfe, 0x80, 0xf0, 0x92, - 0xa6, 0x49, 0x4c, 0x25, 0x17, 0x44, 0xd2, 0x92, 0x08, 0x2a, 0xc1, 0xee, 0xa8, 0xd8, 0xc7, 0x4d, - 0xe7, 0xbf, 0x57, 0xee, 0xf1, 0x3c, 0x91, 0x67, 0xc5, 0xd4, 0x8f, 0x38, 0x33, 0xa3, 0x37, 0xd7, - 0x30, 0x8f, 0x3f, 0x06, 0x72, 0xb5, 0x80, 0xdc, 0x1f, 0x43, 0xf4, 0xf5, 0xcb, 0x10, 0x99, 0xcd, - 0x18, 0x43, 0x14, 0x76, 0x2f, 0x7d, 0x27, 0xb4, 0x0c, 0xa9, 0x04, 0xef, 0x25, 0x3a, 0xf8, 0x63, - 0xb8, 0xf8, 0x04, 0xdd, 0x10, 0x90, 0x83, 0x58, 0x9a, 0xc6, 0x5a, 0xaa, 0x09, 0xb7, 0xeb, 0xca, - 0xbd, 0xa9, 0x8b, 0xde, 0x65, 0xbd, 0x70, 0xdf, 0x7c, 0x9b, 0x6e, 0x8e, 0x9e, 0x9d, 0xaf, 0x1d, - 0xeb, 0x62, 0xed, 0x58, 0x3f, 0xd6, 0x8e, 0xf5, 0x69, 0xe3, 0xb4, 0x2e, 0x36, 0x4e, 0xeb, 0xdb, - 0xc6, 0x69, 0xbd, 0x0b, 0x76, 0x0a, 0x9e, 0x66, 0xd3, 0x61, 0x74, 0x46, 0x93, 0x2c, 0xd8, 0xd9, - 0xfb, 0xf2, 0x72, 0xf3, 0x55, 0xf5, 0xd3, 0x8e, 0x5a, 0xda, 0x47, 0x3f, 0x03, 0x00, 0x00, 0xff, - 0xff, 0x58, 0xde, 0x97, 0xfd, 0x1c, 0x03, 0x00, 0x00, + // 488 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xc1, 0x6e, 0xd3, 0x30, + 0x18, 0x6e, 0x58, 0x99, 0xa8, 0x87, 0xb4, 0xca, 0x0c, 0x91, 0x0e, 0x91, 0x54, 0x01, 0x4d, 0xbd, + 0x34, 0x11, 0x70, 0x9b, 0xb8, 0x2c, 0x54, 0x48, 0x08, 0x84, 0x50, 0xa8, 0x38, 0x70, 0xc0, 0x72, + 0x93, 0xbf, 0x5d, 0x20, 0x8e, 0xab, 0xc4, 0xa9, 0xd2, 0xb7, 0xe0, 0x25, 0x78, 0x03, 0x2e, 0xbc, + 0xc1, 0x8e, 0x13, 0x27, 0xc4, 0x21, 0x42, 0xed, 0x1b, 0xe4, 0x09, 0x50, 0x6c, 0x77, 0x14, 0x2a, + 0xb8, 0x38, 0xf6, 0xf7, 0x7d, 0xfe, 0x3e, 0x3b, 0xfe, 0x90, 0x3d, 0xcb, 0x00, 0xd2, 0x69, 0x0c, + 0x49, 0xe4, 0xcd, 0xe9, 0x92, 0x41, 0x2a, 0xbc, 0x39, 0xcd, 0x28, 0xcb, 0xdd, 0x79, 0xc6, 0x05, + 0xc7, 0xf8, 0xb7, 0xc0, 0xd5, 0x82, 0xe3, 0x5e, 0xc8, 0x73, 0xc6, 0x73, 0x22, 0x15, 0x9e, 0x5a, + 0x28, 0xf9, 0xf1, 0xd1, 0x8c, 0xcf, 0xb8, 0xc2, 0x9b, 0x99, 0x42, 0x9d, 0xcf, 0x7b, 0x68, 0xff, + 0xb5, 0x74, 0xc5, 0x63, 0xd4, 0x5d, 0x40, 0x96, 0xc7, 0x3c, 0x85, 0x88, 0xa8, 0x24, 0xd3, 0xe8, + 0x1b, 0x83, 0x83, 0x47, 0xf7, 0xdd, 0xdd, 0x28, 0xf7, 0xed, 0x46, 0xab, 0xb6, 0xfb, 0xed, 0x8b, + 0xca, 0x6e, 0x05, 0x87, 0x8b, 0x3f, 0x61, 0x0c, 0xe8, 0xae, 0xde, 0x41, 0x68, 0x18, 0xf2, 0x22, + 0x15, 0x44, 0x8d, 0x49, 0xcc, 0x62, 0x61, 0x5e, 0xeb, 0x1b, 0x83, 0xb6, 0x7f, 0x52, 0x57, 0xb6, + 0xb3, 0xa4, 0x2c, 0x39, 0x75, 0xfe, 0x23, 0x76, 0x02, 0x53, 0xb3, 0x67, 0x8a, 0x7c, 0xda, 0x0c, + 0x2f, 0x1b, 0x0a, 0xbf, 0x40, 0x78, 0xca, 0xb3, 0x10, 0x22, 0x92, 0x83, 0x10, 0x09, 0x10, 0x11, + 0x33, 0x30, 0xf7, 0xa4, 0xfb, 0xbd, 0xba, 0xb2, 0x7b, 0xca, 0x7d, 0x57, 0xe3, 0x04, 0x5d, 0x05, + 0xbe, 0x91, 0xd8, 0x38, 0x66, 0x80, 0xdf, 0xa3, 0x1e, 0xa3, 0x25, 0xa1, 0x85, 0xe0, 0x44, 0x92, + 0x9b, 0x0d, 0x69, 0xc1, 0xcc, 0xb6, 0xf4, 0x7c, 0x50, 0x57, 0x76, 0x5f, 0x79, 0xfe, 0x53, 0xea, + 0x04, 0xb7, 0x19, 0x2d, 0xcf, 0x0a, 0xc1, 0x9f, 0x35, 0x8c, 0x0a, 0x78, 0x55, 0x30, 0xfc, 0x10, + 0x75, 0xa6, 0x00, 0x24, 0x82, 0x94, 0x33, 0xf3, 0x7a, 0xdf, 0x18, 0x74, 0xfc, 0xa3, 0xba, 0xb2, + 0xbb, 0xfa, 0x8c, 0x1b, 0xca, 0x09, 0x6e, 0x4c, 0x01, 0x46, 0x72, 0xfa, 0xd5, 0x40, 0x87, 0x7f, + 0xfd, 0x71, 0x7c, 0x8a, 0x6e, 0x66, 0x90, 0x43, 0xb6, 0xd0, 0xb7, 0x35, 0xe4, 0xc9, 0xee, 0xd4, + 0x95, 0x7d, 0x4b, 0x39, 0x6d, 0xb3, 0x4e, 0x70, 0xa0, 0x97, 0xf2, 0x8a, 0x1f, 0x10, 0x5e, 0xd0, + 0x24, 0x8e, 0xa8, 0xe0, 0x19, 0x11, 0xb4, 0x24, 0x19, 0x15, 0x20, 0x5f, 0xa3, 0xe3, 0x3f, 0x69, + 0x5e, 0xf2, 0x47, 0x65, 0x9f, 0xcc, 0x62, 0x71, 0x5e, 0x4c, 0xdc, 0x90, 0x33, 0x5d, 0x25, 0xfd, + 0x19, 0xe6, 0xd1, 0x47, 0x4f, 0x2c, 0xe7, 0x90, 0xbb, 0x23, 0x08, 0xbf, 0x7d, 0x19, 0x22, 0xdd, + 0xb4, 0x11, 0x84, 0x41, 0xf7, 0xca, 0x77, 0x4c, 0xcb, 0x80, 0x0a, 0xf0, 0x9f, 0x5f, 0xac, 0x2c, + 0xe3, 0x72, 0x65, 0x19, 0x3f, 0x57, 0x96, 0xf1, 0x69, 0x6d, 0xb5, 0x2e, 0xd7, 0x56, 0xeb, 0xfb, + 0xda, 0x6a, 0xbd, 0xf3, 0xb6, 0x12, 0x26, 0xe9, 0x64, 0x18, 0x9e, 0xd3, 0x38, 0xf5, 0xb6, 0x8a, + 0x5f, 0x5e, 0x55, 0x5f, 0xc6, 0x4d, 0xf6, 0x65, 0x6b, 0x1f, 0xff, 0x0a, 0x00, 0x00, 0xff, 0xff, + 0x0c, 0xc8, 0xf7, 0x19, 0x1d, 0x03, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -217,16 +217,6 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - { - size := m.ValidatorTaxRate.Size() - i -= size - if _, err := m.ValidatorTaxRate.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintParams(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x32 if len(m.FeeDenom) > 0 { i -= len(m.FeeDenom) copy(dAtA[i:], m.FeeDenom) @@ -282,6 +272,16 @@ func (m *VersionedParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.ValidatorTaxRate.Size() + i -= size + if _, err := m.ValidatorTaxRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 if m.ReserveTime != 0 { i = encodeVarintParams(dAtA, i, uint64(m.ReserveTime)) i-- @@ -322,8 +322,6 @@ func (m *Params) Size() (n int) { if l > 0 { n += 1 + l + sovParams(uint64(l)) } - l = m.ValidatorTaxRate.Size() - n += 1 + l + sovParams(uint64(l)) return n } @@ -336,6 +334,8 @@ func (m *VersionedParams) Size() (n int) { if m.ReserveTime != 0 { n += 1 + sovParams(uint64(m.ReserveTime)) } + l = m.ValidatorTaxRate.Size() + n += 1 + l + sovParams(uint64(l)) return n } @@ -496,40 +496,6 @@ func (m *Params) Unmarshal(dAtA []byte) error { } m.FeeDenom = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValidatorTaxRate", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowParams - } - 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 ErrInvalidLengthParams - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthParams - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.ValidatorTaxRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) @@ -599,6 +565,40 @@ func (m *VersionedParams) Unmarshal(dAtA []byte) error { break } } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorTaxRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + 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 ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ValidatorTaxRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/storage/keeper/payment.go b/x/storage/keeper/payment.go index 4b0d452e8..39e460964 100644 --- a/x/storage/keeper/payment.go +++ b/x/storage/keeper/payment.go @@ -195,8 +195,11 @@ func (k Keeper) GetBucketBill(ctx sdk.Context, bucketInfo *storagetypes.BucketIn }) totalUserOutRate = totalUserOutRate.Add(rate) } - params := k.paymentKeeper.GetParams(ctx) - validatorTaxRate := params.ValidatorTaxRate.MulInt(totalUserOutRate).TruncateInt() + versionedParams, err := k.paymentKeeper.GetVersionedParamsWithTs(ctx, bucketInfo.BillingInfo.PriceTime) + if err != nil { + return userFlows, fmt.Errorf("failed to get validator tax rate: %w, time: %d", err, bucketInfo.BillingInfo.PriceTime) + } + validatorTaxRate := versionedParams.ValidatorTaxRate.MulInt(totalUserOutRate).TruncateInt() if validatorTaxRate.IsPositive() { userFlows.Flows = append(userFlows.Flows, types.OutFlow{ ToAddress: types.ValidatorTaxPoolAddress.String(), diff --git a/x/storage/keeper/payment_test.go b/x/storage/keeper/payment_test.go index 9450f09cb..66c5af5c9 100644 --- a/x/storage/keeper/payment_test.go +++ b/x/storage/keeper/payment_test.go @@ -76,7 +76,7 @@ func (s *IntegrationTestSuiteWithoutMock) SetupTest() { s.T().Logf("s.UserAddr: %s, balance: %s", s.UserAddr, balance) } -func (s *IntegrationTestSuiteWithoutMock) TestCreateCreateBucket_Payment() { +func (s *IntegrationTestSuiteWithoutMock) TestCreateBucket_Payment() { ctx := s.ctx.WithBlockTime(time.Now()) // mock create bucket ChargedReadQuota := uint64(1000) @@ -99,7 +99,7 @@ func (s *IntegrationTestSuiteWithoutMock) TestCreateCreateBucket_Payment() { // mock add a object t2 := t1 + 5000 ctx = ctx.WithBlockTime(ctx.BlockTime().Add(time.Duration(t2) * time.Second)) - bucket.BillingInfo.PriceTime = t2 + bucket.BillingInfo.PriceTime = ctx.BlockTime().Unix() object := types.ObjectInfo{ PayloadSize: 100, CreateAt: ctx.BlockTime().Unix(),