@@ -18,6 +18,86 @@ use move_core_types::{account_address::AccountAddress, language_storage::StructT
18
18
use std:: str:: FromStr ;
19
19
use tracing:: { debug, info} ;
20
20
21
+ pub enum FailedComparison {
22
+ MissingStateValue ( StateKey ) ,
23
+ NotMissingStateValue ( StateKey ) ,
24
+ RawStateDiverge {
25
+ movement_state_key : StateKey ,
26
+ movement_value : Bytes ,
27
+ maptos_state_value : Bytes ,
28
+ } ,
29
+ AccountDiverge {
30
+ address : AccountAddress ,
31
+ movement_account : AccountResource ,
32
+ movement_aptos_account : AccountResource ,
33
+ } ,
34
+ BalanceDiverge {
35
+ address : AccountAddress ,
36
+ movement_balance : u64 ,
37
+ movement_aptos_balance : u64 ,
38
+ } ,
39
+ }
40
+
41
+ impl From < FailedComparison > for ValidationError {
42
+ fn from ( fail : FailedComparison ) -> Self {
43
+ match fail {
44
+ FailedComparison :: MissingStateValue ( movement_state_key) => ValidationError :: Unsatisfied (
45
+ format ! (
46
+ "Movement Aptos is missing a value for {:?}" ,
47
+ movement_state_key
48
+ )
49
+ . into ( ) ,
50
+ ) ,
51
+ FailedComparison :: NotMissingStateValue ( movement_state_key) => ValidationError :: Unsatisfied (
52
+ format ! (
53
+ "Movement Aptos is unexpectedly not missing a value for {:?}" ,
54
+ movement_state_key
55
+ )
56
+ . into ( ) ,
57
+ ) ,
58
+ FailedComparison :: RawStateDiverge {
59
+ movement_state_key,
60
+ movement_value,
61
+ maptos_state_value,
62
+ } => ValidationError :: Unsatisfied (
63
+ format ! (
64
+ "Movement state value for {:?} is {:?}, while Movement Aptos state value is {:?}" ,
65
+ movement_state_key,
66
+ movement_value,
67
+ maptos_state_value
68
+ )
69
+ . into ( ) ,
70
+ ) ,
71
+ FailedComparison :: AccountDiverge {
72
+ address,
73
+ movement_account,
74
+ movement_aptos_account,
75
+ } => ValidationError :: Unsatisfied (
76
+ format ! (
77
+ "Movement account for {:?} is {:?}, while Movement Aptos account is {:?}" ,
78
+ address. to_standard_string( ) ,
79
+ movement_account,
80
+ movement_aptos_account
81
+ )
82
+ . into ( ) ,
83
+ ) ,
84
+ FailedComparison :: BalanceDiverge {
85
+ address,
86
+ movement_balance,
87
+ movement_aptos_balance,
88
+ } => ValidationError :: Unsatisfied (
89
+ format ! (
90
+ "Movement balance for 0x{} is {} coin(s), while Movement Aptos balance is {} coin(s)" ,
91
+ address. short_str_lossless( ) ,
92
+ movement_balance,
93
+ movement_aptos_balance
94
+ )
95
+ . into ( ) ,
96
+ ) ,
97
+ }
98
+ }
99
+ }
100
+
21
101
/// This check iterates over all global state keys starting at ledger version 0.
22
102
/// For each state key it fetches the state view for the latest ledger version,
23
103
/// from the old Movment database and the new Aptos database. The state view bytes
@@ -34,7 +114,7 @@ impl GlobalStorageIncludes {
34
114
mvt_version : u64 ,
35
115
movement_aptos_storage : & MovementAptosStorage ,
36
116
aptos_version : u64 ,
37
- ) -> Result < ( ) , ValidationError > {
117
+ ) -> Result < Vec < FailedComparison > , ValidationError > {
38
118
info ! ( "checking global state keys and values" ) ;
39
119
debug ! ( "movement_ledger_version: {:?}" , mvt_version) ;
40
120
debug ! ( "aptos_ledger_version: {:?}" , aptos_version) ;
@@ -60,6 +140,8 @@ impl GlobalStorageIncludes {
60
140
let account = StructTag :: from_str ( "0x1::account::Account" ) . unwrap ( ) ;
61
141
let coin = StructTag :: from_str ( "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>" ) . unwrap ( ) ;
62
142
143
+ let mut failed_list = vec ! [ ] ;
144
+
63
145
for movement_state_key in movement_global_state_keys {
64
146
debug ! (
65
147
"processing movement_state_key {}: {:?}" ,
@@ -75,41 +157,56 @@ impl GlobalStorageIncludes {
75
157
76
158
match movement_value {
77
159
Some ( movement_value) => {
78
- let maptos_state_value = maptos_state_view
160
+ let maptos_state_value = match maptos_state_view
79
161
. get_state_value_bytes ( & movement_state_key)
80
162
. map_err ( |e| ValidationError :: Internal ( e. into ( ) ) ) ?
81
- . ok_or ( ValidationError :: Unsatisfied (
82
- format ! (
83
- "Movement Aptos is missing a value for {:?}" ,
84
- movement_state_key
85
- )
86
- . into ( ) ,
87
- ) ) ?;
163
+ {
164
+ Some ( val) => val,
165
+ None => {
166
+ failed_list
167
+ . push ( FailedComparison :: MissingStateValue ( movement_state_key) ) ;
168
+ break ;
169
+ } ,
170
+ } ;
88
171
89
172
if let StateKeyInner :: AccessPath ( p) = movement_state_key. inner ( ) {
90
173
match p. get_path ( ) {
91
- Path :: Resource ( tag) if tag == account => Self :: compare_accounts (
92
- p. address ,
93
- movement_value,
94
- maptos_state_value,
95
- ) ?,
96
- Path :: Resource ( tag) if tag == coin => Self :: compare_balances (
97
- p. address ,
98
- movement_value,
99
- maptos_state_value,
100
- ) ?,
101
- _ => Self :: compare_raw_state (
102
- movement_state_key,
103
- movement_value,
104
- maptos_state_value,
105
- ) ?,
174
+ Path :: Resource ( tag) if tag == account => {
175
+ if let Some ( fail) = Self :: compare_accounts (
176
+ p. address ,
177
+ movement_value,
178
+ maptos_state_value,
179
+ ) ? {
180
+ failed_list. push ( fail) ;
181
+ }
182
+ } ,
183
+ Path :: Resource ( tag) if tag == coin => {
184
+ if let Some ( fail) = Self :: compare_balances (
185
+ p. address ,
186
+ movement_value,
187
+ maptos_state_value,
188
+ ) ? {
189
+ failed_list. push ( fail) ;
190
+ }
191
+ } ,
192
+ _ => {
193
+ if let Some ( fail) = Self :: compare_raw_state (
194
+ movement_state_key,
195
+ movement_value,
196
+ maptos_state_value,
197
+ ) {
198
+ failed_list. push ( fail) ;
199
+ }
200
+ } ,
106
201
}
107
202
} else {
108
- Self :: compare_raw_state (
203
+ if let Some ( fail ) = Self :: compare_raw_state (
109
204
movement_state_key,
110
205
movement_value,
111
206
maptos_state_value,
112
- ) ?;
207
+ ) {
208
+ failed_list. push ( fail) ;
209
+ } ;
113
210
}
114
211
} ,
115
212
None => {
@@ -120,13 +217,9 @@ impl GlobalStorageIncludes {
120
217
. map_err ( |e| ValidationError :: Internal ( e. into ( ) ) ) ?
121
218
{
122
219
Some ( _) => {
123
- return Err ( ValidationError :: Unsatisfied (
124
- format ! (
125
- "Movement Aptos is unexpectedly not missing a value for {:?}" ,
126
- movement_state_key
127
- )
128
- . into ( ) ,
129
- ) ) ;
220
+ failed_list
221
+ . push ( FailedComparison :: NotMissingStateValue ( movement_state_key) ) ;
222
+ break ;
130
223
} ,
131
224
None => { } ,
132
225
}
@@ -135,7 +228,7 @@ impl GlobalStorageIncludes {
135
228
count += 1 ;
136
229
}
137
230
138
- Ok ( ( ) )
231
+ Ok ( failed_list )
139
232
}
140
233
141
234
pub fn satisfies (
@@ -151,39 +244,42 @@ impl GlobalStorageIncludes {
151
244
. latest_ledger_version ( )
152
245
. map_err ( |e| ValidationError :: Internal ( e. into ( ) ) ) ?;
153
246
154
- GlobalStorageIncludes :: compare_db (
247
+ let mut failed_list = GlobalStorageIncludes :: compare_db (
155
248
movement_storage,
156
249
movement_ledger_version,
157
250
movement_aptos_storage,
158
251
aptos_ledger_version,
159
- )
252
+ ) ?;
253
+
254
+ if failed_list. len ( ) > 0 {
255
+ let val = failed_list. swap_remove ( 0 ) ;
256
+ Err ( val. into ( ) )
257
+ } else {
258
+ Ok ( ( ) )
259
+ }
160
260
}
161
261
162
262
fn compare_raw_state (
163
263
movement_state_key : StateKey ,
164
264
movement_value : Bytes ,
165
265
maptos_state_value : Bytes ,
166
- ) -> Result < ( ) , ValidationError > {
266
+ ) -> Option < FailedComparison > {
167
267
if movement_value != maptos_state_value {
168
- Err ( ValidationError :: Unsatisfied (
169
- format ! (
170
- "Movement state value for {:?} is {:?}, while Movement Aptos state value is {:?}" ,
171
- movement_state_key,
172
- movement_value,
173
- maptos_state_value
174
- )
175
- . into ( ) ,
176
- ) )
268
+ Some ( FailedComparison :: RawStateDiverge {
269
+ movement_state_key,
270
+ movement_value,
271
+ maptos_state_value,
272
+ } )
177
273
} else {
178
- Ok ( ( ) )
274
+ None
179
275
}
180
276
}
181
277
182
278
fn compare_accounts (
183
279
address : AccountAddress ,
184
280
movement_value : Bytes ,
185
281
maptos_state_value : Bytes ,
186
- ) -> Result < ( ) , ValidationError > {
282
+ ) -> Result < Option < FailedComparison > , ValidationError > {
187
283
let movement_account = bcs:: from_bytes :: < AccountResource > ( & movement_value)
188
284
. map_err ( |e| ValidationError :: Internal ( e. into ( ) ) ) ?;
189
285
let movement_aptos_account = bcs:: from_bytes :: < AccountResource > ( & maptos_state_value)
@@ -196,25 +292,21 @@ impl GlobalStorageIncludes {
196
292
) ;
197
293
198
294
if movement_account != movement_aptos_account {
199
- Err ( ValidationError :: Unsatisfied (
200
- format ! (
201
- "Movement account for {:?} is {:?}, while Movement Aptos account is {:?}" ,
202
- address. to_standard_string( ) ,
203
- movement_account,
204
- movement_aptos_account
205
- )
206
- . into ( ) ,
207
- ) )
295
+ Ok ( Some ( FailedComparison :: AccountDiverge {
296
+ address,
297
+ movement_account,
298
+ movement_aptos_account,
299
+ } ) )
208
300
} else {
209
- Ok ( ( ) )
301
+ Ok ( None )
210
302
}
211
303
}
212
304
213
305
fn compare_balances (
214
306
address : AccountAddress ,
215
307
movement_value : Bytes ,
216
308
maptos_state_value : Bytes ,
217
- ) -> Result < ( ) , ValidationError > {
309
+ ) -> Result < Option < FailedComparison > , ValidationError > {
218
310
let movement_balance = bcs:: from_bytes :: < CoinStoreResourceUntyped > ( & movement_value)
219
311
. map_err ( |e| ValidationError :: Internal ( e. into ( ) ) ) ?
220
312
. coin ( ) ;
@@ -230,17 +322,13 @@ impl GlobalStorageIncludes {
230
322
) ;
231
323
232
324
if movement_balance != movement_aptos_balance {
233
- Err ( ValidationError :: Unsatisfied (
234
- format ! (
235
- "Movement balance for 0x{} is {} coin(s), while Movement Aptos balance is {} coin(s)" ,
236
- address. short_str_lossless( ) ,
237
- movement_balance,
238
- movement_aptos_balance
239
- )
240
- . into ( ) ,
241
- ) )
325
+ Ok ( Some ( FailedComparison :: BalanceDiverge {
326
+ address,
327
+ movement_balance,
328
+ movement_aptos_balance,
329
+ } ) )
242
330
} else {
243
- Ok ( ( ) )
331
+ Ok ( None )
244
332
}
245
333
}
246
334
}
0 commit comments