Skip to content

Commit 9c1827d

Browse files
committed
unit test
1 parent 11d5da5 commit 9c1827d

3 files changed

Lines changed: 195 additions & 9 deletions

File tree

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,13 @@ require (
177177
)
178178

179179
replace (
180-
cosmossdk.io/api => github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20250424012533-3644b91a4a5c
181-
cosmossdk.io/math => github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20250424012533-3644b91a4a5c
180+
cosmossdk.io/api => ../greenfield-cosmos-sdk/api
181+
cosmossdk.io/math => ../greenfield-cosmos-sdk/math
182182
github.com/btcsuite/btcd => github.com/btcsuite/btcd v0.23.0
183183
github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-cometbft v1.3.2-0.20250421115205-d0c58e3042cf
184184
github.com/cometbft/cometbft-db => github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1
185185
github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
186-
github.com/cosmos/cosmos-sdk => github.com/bnb-chain/greenfield-cosmos-sdk v1.10.2
186+
github.com/cosmos/cosmos-sdk => ../greenfield-cosmos-sdk
187187
github.com/cosmos/iavl => github.com/bnb-chain/greenfield-iavl v0.20.1
188188
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
189189
github.com/wercker/journalhook => github.com/wercker/journalhook v0.0.0-20230927020745-64542ffa4117

go.sum

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,6 @@ github.com/bnb-chain/greenfield-cometbft v1.3.2-0.20250421115205-d0c58e3042cf h1
7676
github.com/bnb-chain/greenfield-cometbft v1.3.2-0.20250421115205-d0c58e3042cf/go.mod h1:KHJjaV8GR/HLVUNpA8l+ro8clFSlwEbyNZIujf8c27w=
7777
github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1 h1:XcWulGacHVRiSCx90Q8Y//ajOrLNBQWR/KDB89dy3cU=
7878
github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1/go.mod h1:ey1CiK4bYo1RBNJLRiVbYr5CMdSxci9S/AZRINLtppI=
79-
github.com/bnb-chain/greenfield-cosmos-sdk v1.10.2 h1:7YYVzEq3eDTB0UJoomFAtsPzzL0O8Gu0i/KEgVsb/oM=
80-
github.com/bnb-chain/greenfield-cosmos-sdk v1.10.2/go.mod h1:3yqFQxEw05CP1uCyKZtUJjP5N5E+OYALrfJnSWLTE6c=
81-
github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20250424012533-3644b91a4a5c h1:+kWAQ4r5KXkReB7IE9Z91mtOUNeIKG0KRjC/v7kuxP0=
82-
github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20250424012533-3644b91a4a5c/go.mod h1:YzvJKV9ZaLfB0Bt5NiTId53lhMUFDmeBJpFddWNoDeQ=
83-
github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20250424012533-3644b91a4a5c h1:0LTfgCXv6gk3PubhFMQwRHgo510hxeyacOHuv9ADebA=
84-
github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20250424012533-3644b91a4a5c/go.mod h1:An0MllWJY6PxibUpnwGk8jOm+a/qIxlKmL5Zyp9NnaM=
8579
github.com/bnb-chain/greenfield-iavl v0.20.1 h1:y3L64GU99otNp27/xLVBTDbv4eroR6CzoYz0rbaVotM=
8680
github.com/bnb-chain/greenfield-iavl v0.20.1/go.mod h1:oLksTs8dfh7DYIKBro7hbRQ+ewls7ghJ27pIXlbEXyI=
8781
github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA=
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package keeper_test
2+
3+
import (
4+
"time"
5+
6+
sdk "github.com/cosmos/cosmos-sdk/types"
7+
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
8+
"github.com/golang/mock/gomock"
9+
10+
"github.com/bnb-chain/greenfield/testutil/sample"
11+
paymenttypes "github.com/bnb-chain/greenfield/x/payment/types"
12+
sptypes "github.com/bnb-chain/greenfield/x/sp/types"
13+
"github.com/bnb-chain/greenfield/x/storage/types"
14+
vgtypes "github.com/bnb-chain/greenfield/x/virtualgroup/types"
15+
)
16+
17+
func (s *TestSuite) TestUpdateObjectContent_IBIConsistency() {
18+
owner := sample.RandAccAddress()
19+
minChargeSize := uint64(1024 * 1024) // 1MB
20+
21+
gvgFamily := &vgtypes.GlobalVirtualGroupFamily{
22+
Id: 1,
23+
PrimarySpId: 1,
24+
GlobalVirtualGroupIds: []uint32{1},
25+
VirtualPaymentAddress: sample.RandAccAddress().String(),
26+
}
27+
28+
gvg := &vgtypes.GlobalVirtualGroup{
29+
Id: 1,
30+
PrimarySpId: 1,
31+
SecondarySpIds: []uint32{2, 3, 4, 5, 6, 7},
32+
VirtualPaymentAddress: sample.RandAccAddress().String(),
33+
}
34+
35+
sp := &sptypes.StorageProvider{
36+
Id: 1,
37+
OperatorAddress: owner.String(),
38+
Status: sptypes.STATUS_IN_SERVICE,
39+
}
40+
41+
price := sptypes.GlobalSpStorePrice{
42+
ReadPrice: sdk.NewDec(100),
43+
PrimaryStorePrice: sdk.NewDec(1000),
44+
SecondaryStorePrice: sdk.NewDec(500),
45+
}
46+
47+
paymentParams := paymenttypes.VersionedParams{
48+
ReserveTime: 10000,
49+
ValidatorTaxRate: sdk.NewDecWithPrec(1, 2), // 1%
50+
}
51+
52+
bucketName := "test-bucket"
53+
objectName := "test-object"
54+
originalPayloadSize := uint64(10 * 1024 * 1024) // 10MB
55+
56+
bucketInfo := &types.BucketInfo{
57+
Owner: owner.String(),
58+
BucketName: bucketName,
59+
Id: sdk.NewUint(1),
60+
PaymentAddress: owner.String(),
61+
GlobalVirtualGroupFamilyId: gvgFamily.Id,
62+
ChargedReadQuota: 0,
63+
BucketStatus: types.BUCKET_STATUS_CREATED,
64+
}
65+
66+
objectInfo := &types.ObjectInfo{
67+
Id: sdk.NewUint(1),
68+
BucketName: bucketName,
69+
ObjectName: objectName,
70+
Owner: owner.String(),
71+
PayloadSize: originalPayloadSize,
72+
ObjectStatus: types.OBJECT_STATUS_SEALED,
73+
LocalVirtualGroupId: 1,
74+
Visibility: types.VISIBILITY_TYPE_PRIVATE,
75+
CreateAt: 100,
76+
}
77+
78+
makeIBI := func() *types.InternalBucketInfo {
79+
return &types.InternalBucketInfo{
80+
TotalChargeSize: originalPayloadSize,
81+
LocalVirtualGroups: []*types.LocalVirtualGroup{
82+
{
83+
Id: 1,
84+
GlobalVirtualGroupId: gvg.Id,
85+
StoredSize: originalPayloadSize,
86+
TotalChargeSize: originalPayloadSize,
87+
},
88+
},
89+
}
90+
}
91+
92+
setupMocks := func() {
93+
s.virtualGroupKeeper.EXPECT().GetGVGFamily(gomock.Any(), gvgFamily.Id).
94+
Return(gvgFamily, true).AnyTimes()
95+
s.virtualGroupKeeper.EXPECT().GetGVG(gomock.Any(), gvg.Id).
96+
Return(gvg, true).AnyTimes()
97+
s.virtualGroupKeeper.EXPECT().GetGlobalVirtualGroupIfAvailable(gomock.Any(), gvg.Id, gomock.Any()).
98+
Return(gvg, nil).AnyTimes()
99+
s.virtualGroupKeeper.EXPECT().SetGVGAndEmitUpdateEvent(gomock.Any(), gomock.Any()).
100+
Return(nil).AnyTimes()
101+
s.spKeeper.EXPECT().MustGetStorageProvider(gomock.Any(), sp.Id).
102+
Return(sp).AnyTimes()
103+
s.spKeeper.EXPECT().GetGlobalSpStorePriceByTime(gomock.Any(), gomock.Any()).
104+
Return(price, nil).AnyTimes()
105+
s.paymentKeeper.EXPECT().GetVersionedParamsWithTs(gomock.Any(), gomock.Any()).
106+
Return(paymentParams, nil).AnyTimes()
107+
s.paymentKeeper.EXPECT().ApplyUserFlowsList(gomock.Any(), gomock.Any()).
108+
Return(nil).AnyTimes()
109+
s.paymentKeeper.EXPECT().UpdateStreamRecordByAddr(gomock.Any(), gomock.Any()).
110+
Return(&paymenttypes.StreamRecord{
111+
StaticBalance: sdk.NewInt(1000000000),
112+
}, nil).AnyTimes()
113+
s.paymentKeeper.EXPECT().MergeOutFlows(gomock.Any()).DoAndReturn(
114+
func(flows []paymenttypes.OutFlow) []paymenttypes.OutFlow {
115+
return flows
116+
}).AnyTimes()
117+
}
118+
119+
s.Run("before Taiga upgrade - IBI is stale", func() {
120+
s.SetupTest()
121+
// store versioned params at t=1 so GetObjectChargeSize can find them for object with CreateAt=1
122+
s.ctx = s.ctx.WithBlockTime(time.Unix(1, 0))
123+
err := s.storageKeeper.SetVersionedParamsWithTs(s.ctx, types.VersionedParams{MinChargeSize: minChargeSize})
124+
s.Require().NoError(err)
125+
s.ctx = s.ctx.WithBlockTime(time.Unix(100, 0))
126+
127+
setupMocks()
128+
129+
s.storageKeeper.StoreBucketInfo(s.ctx, bucketInfo)
130+
s.storageKeeper.StoreObjectInfo(s.ctx, objectInfo)
131+
s.storageKeeper.SetInternalBucketInfo(s.ctx, bucketInfo.Id, makeIBI())
132+
133+
err = s.storageKeeper.UpdateObjectContent(s.ctx, owner, bucketName, objectName, 0, types.UpdateObjectOptions{
134+
Checksums: make([][]byte, 1+len(gvg.SecondarySpIds)),
135+
})
136+
s.Require().NoError(err)
137+
138+
ibi := s.storageKeeper.MustGetInternalBucketInfo(s.ctx, bucketInfo.Id)
139+
140+
// Before Taiga: TotalChargeSize is stale — the original 10MB was NOT reduced by UnChargeObjectStoreFee
141+
// (it modified a separate copy), then SealEmptyObjectOnVirtualGroup added min_charge_size on top.
142+
// Result: 10MB + 1MB = 11MB instead of correct 1MB.
143+
s.Require().Greater(ibi.TotalChargeSize, minChargeSize,
144+
"before Taiga, TotalChargeSize should be inflated due to stale IBI bug")
145+
})
146+
147+
s.Run("after Taiga upgrade - IBI is consistent", func() {
148+
s.SetupTest()
149+
upgradeChecker := func(ctx sdk.Context, name string) bool {
150+
return name == upgradetypes.Serengeti || name == upgradetypes.Taiga
151+
}
152+
header := s.ctx.BlockHeader()
153+
header.Time = time.Unix(1, 0)
154+
s.ctx = sdk.NewContext(s.ctx.MultiStore(), header, false, upgradeChecker, s.ctx.Logger())
155+
156+
err := s.storageKeeper.SetParams(s.ctx, types.DefaultParams())
157+
s.Require().NoError(err)
158+
err = s.storageKeeper.SetVersionedParamsWithTs(s.ctx, types.VersionedParams{MinChargeSize: minChargeSize})
159+
s.Require().NoError(err)
160+
// advance block time past the params timestamp
161+
header.Time = time.Unix(100, 0)
162+
s.ctx = sdk.NewContext(s.ctx.MultiStore(), header, false, upgradeChecker, s.ctx.Logger())
163+
164+
setupMocks()
165+
166+
s.storageKeeper.StoreBucketInfo(s.ctx, bucketInfo)
167+
s.storageKeeper.StoreObjectInfo(s.ctx, objectInfo)
168+
s.storageKeeper.SetInternalBucketInfo(s.ctx, bucketInfo.Id, makeIBI())
169+
170+
err = s.storageKeeper.UpdateObjectContent(s.ctx, owner, bucketName, objectName, 0, types.UpdateObjectOptions{
171+
Checksums: make([][]byte, 1+len(gvg.SecondarySpIds)),
172+
})
173+
s.Require().NoError(err)
174+
175+
ibi := s.storageKeeper.MustGetInternalBucketInfo(s.ctx, bucketInfo.Id)
176+
177+
// After Taiga: TotalChargeSize should be exactly min_charge_size (1MB).
178+
// UnChargeObjectStoreFee correctly reduced 10MB on the same IBI copy,
179+
// then SealEmptyObjectOnVirtualGroup added min_charge_size for the empty object.
180+
s.Require().Equal(minChargeSize, ibi.TotalChargeSize,
181+
"after Taiga, TotalChargeSize should equal min_charge_size")
182+
183+
hasNonZeroLVG := false
184+
for _, lvg := range ibi.LocalVirtualGroups {
185+
if lvg.TotalChargeSize > 0 {
186+
s.Require().Equal(minChargeSize, lvg.TotalChargeSize)
187+
hasNonZeroLVG = true
188+
}
189+
}
190+
s.Require().True(hasNonZeroLVG, "should have exactly one LVG with min_charge_size")
191+
})
192+
}

0 commit comments

Comments
 (0)