Skip to content

Commit c122fdf

Browse files
committed
return all errors and not only the first
1 parent c97a9e8 commit c122fdf

File tree

1 file changed

+157
-69
lines changed

1 file changed

+157
-69
lines changed

movement-migration/validation-tool/src/checks/node/global_storage_includes.rs

Lines changed: 157 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,86 @@ use move_core_types::{account_address::AccountAddress, language_storage::StructT
1818
use std::str::FromStr;
1919
use tracing::{debug, info};
2020

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+
21101
/// This check iterates over all global state keys starting at ledger version 0.
22102
/// For each state key it fetches the state view for the latest ledger version,
23103
/// from the old Movment database and the new Aptos database. The state view bytes
@@ -34,7 +114,7 @@ impl GlobalStorageIncludes {
34114
mvt_version: u64,
35115
movement_aptos_storage: &MovementAptosStorage,
36116
aptos_version: u64,
37-
) -> Result<(), ValidationError> {
117+
) -> Result<Vec<FailedComparison>, ValidationError> {
38118
info!("checking global state keys and values");
39119
debug!("movement_ledger_version: {:?}", mvt_version);
40120
debug!("aptos_ledger_version: {:?}", aptos_version);
@@ -60,6 +140,8 @@ impl GlobalStorageIncludes {
60140
let account = StructTag::from_str("0x1::account::Account").unwrap();
61141
let coin = StructTag::from_str("0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>").unwrap();
62142

143+
let mut failed_list = vec![];
144+
63145
for movement_state_key in movement_global_state_keys {
64146
debug!(
65147
"processing movement_state_key {}: {:?}",
@@ -75,41 +157,56 @@ impl GlobalStorageIncludes {
75157

76158
match movement_value {
77159
Some(movement_value) => {
78-
let maptos_state_value = maptos_state_view
160+
let maptos_state_value = match maptos_state_view
79161
.get_state_value_bytes(&movement_state_key)
80162
.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+
};
88171

89172
if let StateKeyInner::AccessPath(p) = movement_state_key.inner() {
90173
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+
},
106201
}
107202
} else {
108-
Self::compare_raw_state(
203+
if let Some(fail) = Self::compare_raw_state(
109204
movement_state_key,
110205
movement_value,
111206
maptos_state_value,
112-
)?;
207+
) {
208+
failed_list.push(fail);
209+
};
113210
}
114211
},
115212
None => {
@@ -120,13 +217,9 @@ impl GlobalStorageIncludes {
120217
.map_err(|e| ValidationError::Internal(e.into()))?
121218
{
122219
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;
130223
},
131224
None => {},
132225
}
@@ -135,7 +228,7 @@ impl GlobalStorageIncludes {
135228
count += 1;
136229
}
137230

138-
Ok(())
231+
Ok(failed_list)
139232
}
140233

141234
pub fn satisfies(
@@ -151,39 +244,42 @@ impl GlobalStorageIncludes {
151244
.latest_ledger_version()
152245
.map_err(|e| ValidationError::Internal(e.into()))?;
153246

154-
GlobalStorageIncludes::compare_db(
247+
let mut failed_list = GlobalStorageIncludes::compare_db(
155248
movement_storage,
156249
movement_ledger_version,
157250
movement_aptos_storage,
158251
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+
}
160260
}
161261

162262
fn compare_raw_state(
163263
movement_state_key: StateKey,
164264
movement_value: Bytes,
165265
maptos_state_value: Bytes,
166-
) -> Result<(), ValidationError> {
266+
) -> Option<FailedComparison> {
167267
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+
})
177273
} else {
178-
Ok(())
274+
None
179275
}
180276
}
181277

182278
fn compare_accounts(
183279
address: AccountAddress,
184280
movement_value: Bytes,
185281
maptos_state_value: Bytes,
186-
) -> Result<(), ValidationError> {
282+
) -> Result<Option<FailedComparison>, ValidationError> {
187283
let movement_account = bcs::from_bytes::<AccountResource>(&movement_value)
188284
.map_err(|e| ValidationError::Internal(e.into()))?;
189285
let movement_aptos_account = bcs::from_bytes::<AccountResource>(&maptos_state_value)
@@ -196,25 +292,21 @@ impl GlobalStorageIncludes {
196292
);
197293

198294
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+
}))
208300
} else {
209-
Ok(())
301+
Ok(None)
210302
}
211303
}
212304

213305
fn compare_balances(
214306
address: AccountAddress,
215307
movement_value: Bytes,
216308
maptos_state_value: Bytes,
217-
) -> Result<(), ValidationError> {
309+
) -> Result<Option<FailedComparison>, ValidationError> {
218310
let movement_balance = bcs::from_bytes::<CoinStoreResourceUntyped>(&movement_value)
219311
.map_err(|e| ValidationError::Internal(e.into()))?
220312
.coin();
@@ -230,17 +322,13 @@ impl GlobalStorageIncludes {
230322
);
231323

232324
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+
}))
242330
} else {
243-
Ok(())
331+
Ok(None)
244332
}
245333
}
246334
}

0 commit comments

Comments
 (0)