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