@@ -79,53 +79,148 @@ func TestStaleTransactions1(t *testing.T) {
79
79
assert .True (t , errors .As (err , & ConsistencyError {}), "err: %v" , err )
80
80
}
81
81
82
- func TestKeyRegistrationApplicationTxn (t * testing.T ) {
82
+ // TestKeyRegistrationApplicationTxn was merged into TestAllClearedFields
83
+ // which provides more comprehensive coverage of the rewind functionality
84
+
85
+ // TestAllClearedFields verifies that all fields that should be reset during a rewind are properly cleared
86
+ func TestAllClearedFields (t * testing.T ) {
83
87
var a sdk.Address
84
88
a [0 ] = 'a'
85
89
86
- // Set up account with participation and app state
90
+ // Helper functions for pointer values
91
+ uint64Ptr := func (v uint64 ) * uint64 { return & v }
92
+ boolPtr := func (v bool ) * bool { return & v }
93
+ bytesPtr := func (v []byte ) * []byte { return & v }
94
+ stringPtr := func (v string ) * string { return & v }
95
+
96
+ // Create an account with ALL fields populated
87
97
account := models.Account {
88
98
Address : a .String (),
89
- Amount : 100 ,
90
- AmountWithoutPendingRewards : 100 ,
91
- Round : 8 ,
99
+ Amount : 1000 ,
100
+ AmountWithoutPendingRewards : 980 ,
101
+ PendingRewards : 20 ,
102
+ Rewards : 100 ,
103
+ Round : 10 ,
104
+ Status : "Online" ,
105
+ MinBalance : 200 ,
106
+
107
+ // Keyreg-related fields
92
108
Participation : & models.AccountParticipation {
93
- VoteFirstValid : 100 , VoteLastValid : 200 , VoteKeyDilution : 10000 ,
109
+ VoteFirstValid : 100 ,
110
+ VoteLastValid : 200 ,
111
+ VoteKeyDilution : 10000 ,
112
+ VoteParticipationKey : []byte ("votepk" ),
113
+ SelectionParticipationKey : []byte ("selpk" ),
114
+ StateProofKey : bytesPtr ([]byte ("stpk" )),
94
115
},
95
- AppsLocalState : & []models.ApplicationLocalState {{Id : 123 }},
96
- CreatedApps : & []models.Application {{Id : 456 }},
116
+
117
+ // App-related fields
118
+ AppsLocalState : & []models.ApplicationLocalState {{Id : 123 }},
119
+ AppsTotalExtraPages : uint64Ptr (2 ),
120
+ AppsTotalSchema : & models.ApplicationStateSchema {NumByteSlice : 10 , NumUint : 10 },
121
+ CreatedApps : & []models.Application {{Id : 456 }},
122
+ TotalAppsOptedIn : 5 ,
123
+ TotalBoxBytes : 1000 ,
124
+ TotalBoxes : 10 ,
125
+ TotalCreatedApps : 3 ,
126
+
127
+ // Asset-related fields
128
+ Assets : & []models.AssetHolding {{AssetId : 789 , Amount : 50 }},
129
+ CreatedAssets : & []models.Asset {{Index : 999 }},
130
+ TotalAssetsOptedIn : 2 ,
131
+ TotalCreatedAssets : 1 ,
132
+
133
+ // Fields set at account creation/deletion
134
+ ClosedAtRound : uint64Ptr (500 ),
135
+ CreatedAtRound : uint64Ptr (1 ),
136
+ Deleted : boolPtr (false ),
137
+
138
+ // Incentive fields
139
+ IncentiveEligible : boolPtr (true ),
140
+ LastHeartbeat : uint64Ptr (7 ),
141
+ LastProposed : uint64Ptr (6 ),
142
+
143
+ // Auth fields
144
+ AuthAddr : stringPtr ("authaddr" ),
145
+ SigType : (* models .AccountSigType )(stringPtr (string (models .AccountSigTypeSig ))),
97
146
}
98
147
99
- // Create test transactions - one KeyReg and one AppCall
100
- keyregTxn := idb.TxnRow {
101
- Round : 7 ,
102
- Txn : & sdk.SignedTxnWithAD {SignedTxn : sdk.SignedTxn {
103
- Txn : sdk.Transaction {Type : sdk .KeyRegistrationTx , Header : sdk.Header {Sender : a }},
104
- }}}
105
-
106
- appCallTxn := idb.TxnRow {
107
- Round : 8 ,
108
- Txn : & sdk.SignedTxnWithAD {SignedTxn : sdk.SignedTxn {
109
- Txn : sdk.Transaction {Type : sdk .ApplicationCallTx , Header : sdk.Header {Sender : a }},
110
- }}}
111
-
112
- // Send both transactions to the mock DB
113
- ch := make (chan idb.TxnRow , 2 )
114
- ch <- appCallTxn
115
- ch <- keyregTxn
148
+ // Create various transaction types for testing
149
+ txns := []idb.TxnRow {
150
+ { // Application call
151
+ Round : 10 ,
152
+ Txn : & sdk.SignedTxnWithAD {SignedTxn : sdk.SignedTxn {
153
+ Txn : sdk.Transaction {Type : sdk .ApplicationCallTx , Header : sdk.Header {Sender : a }},
154
+ }},
155
+ },
156
+ { // Key registration
157
+ Round : 9 ,
158
+ Txn : & sdk.SignedTxnWithAD {SignedTxn : sdk.SignedTxn {
159
+ Txn : sdk.Transaction {Type : sdk .KeyRegistrationTx , Header : sdk.Header {Sender : a }},
160
+ }},
161
+ },
162
+ { // Payment
163
+ Round : 8 ,
164
+ Txn : & sdk.SignedTxnWithAD {SignedTxn : sdk.SignedTxn {
165
+ Txn : sdk.Transaction {
166
+ Type : sdk .PaymentTx ,
167
+ Header : sdk.Header {Sender : a },
168
+ PaymentTxnFields : sdk.PaymentTxnFields {Amount : 10 },
169
+ },
170
+ }},
171
+ },
172
+ }
173
+
174
+ // Set up mock DB
175
+ ch := make (chan idb.TxnRow , len (txns ))
176
+ for _ , txn := range txns {
177
+ ch <- txn
178
+ }
116
179
close (ch )
117
180
var outCh <- chan idb.TxnRow = ch
118
181
119
182
db := & mocks.IndexerDb {}
120
183
db .On ("GetSpecialAccounts" , mock .Anything ).Return (types.SpecialAddresses {}, nil )
121
- db .On ("Transactions" , mock .Anything , mock .Anything ).Return (outCh , uint64 (8 ))
184
+ db .On ("Transactions" , mock .Anything , mock .Anything ).Return (outCh , uint64 (10 ))
122
185
123
186
// Run the rewind
124
- result , err := AccountAtRound (context .Background (), account , 6 , db )
187
+ result , err := AccountAtRound (context .Background (), account , 5 , db )
125
188
assert .NoError (t , err )
126
189
127
- // Verify that both participation and app state fields are nil after rewind
128
- assert .Nil (t , result .Participation , "Participation should be nil after rewinding KeyRegistration transaction" )
129
- assert .Nil (t , result .AppsLocalState , "AppsLocalState should be nil after rewinding ApplicationCall transaction" )
130
- assert .Nil (t , result .CreatedApps , "CreatedApps should be nil after rewinding ApplicationCall transaction" )
190
+ // Verify all fields that should be reset or zeroed out
191
+
192
+ // Fields that should be preserved/changed correctly
193
+ assert .Equal (t , a .String (), result .Address , "Address should be preserved" )
194
+
195
+ // Fields that are explicitly zeroed out
196
+ assert .Equal (t , uint64 (0 ), result .Rewards , "Rewards should be 0" )
197
+ assert .Equal (t , uint64 (0 ), result .PendingRewards , "PendingRewards should be 0" )
198
+ assert .Equal (t , uint64 (0 ), result .MinBalance , "MinBalance should be 0" )
199
+
200
+ // Fields that are explicitly set to nil
201
+ assert .Nil (t , result .ClosedAtRound , "ClosedAtRound should be nil" )
202
+
203
+ // Fields nulled out by KeyRegistrationTx
204
+ assert .Nil (t , result .Participation , "Participation should be nil" )
205
+
206
+ // Fields nulled out by ApplicationCallTx
207
+ assert .Nil (t , result .AppsLocalState , "AppsLocalState should be nil" )
208
+ assert .Nil (t , result .AppsTotalExtraPages , "AppsTotalExtraPages should be nil" )
209
+ assert .Nil (t , result .AppsTotalSchema , "AppsTotalSchema should be nil" )
210
+ assert .Nil (t , result .CreatedApps , "CreatedApps should be nil" )
211
+ assert .Equal (t , uint64 (0 ), result .TotalAppsOptedIn , "TotalAppsOptedIn should be 0" )
212
+ assert .Equal (t , uint64 (0 ), result .TotalBoxBytes , "TotalBoxBytes should be 0" )
213
+ assert .Equal (t , uint64 (0 ), result .TotalBoxes , "TotalBoxes should be 0" )
214
+ assert .Equal (t , uint64 (0 ), result .TotalCreatedApps , "TotalCreatedApps should be 0" )
215
+
216
+ // Incentive fields explicitly set to nil
217
+ assert .Nil (t , result .IncentiveEligible , "IncentiveEligible should be nil" )
218
+ assert .Nil (t , result .LastHeartbeat , "LastHeartbeat should be nil" )
219
+ assert .Nil (t , result .LastProposed , "LastProposed should be nil" )
220
+
221
+ // Assets should be preserved (although updated with AssetConfigTx/AssetTransferTx)
222
+ assert .NotNil (t , result .Assets , "Assets should not be nil" )
223
+
224
+ // Round should be set to the target round
225
+ assert .Equal (t , uint64 (5 ), result .Round , "Round should be set to target round" )
131
226
}
0 commit comments