Skip to content

Commit f44713b

Browse files
committed
add code download mode for comparison testing tool
1 parent 75222b2 commit f44713b

7 files changed

Lines changed: 154 additions & 44 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aptos-move/aptos-e2e-comparison-testing/src/data_collection.rs

Lines changed: 76 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ pub struct DataCollection {
3535
current_dir: PathBuf,
3636
batch_size: u64,
3737
dump_write_set: bool,
38+
skip_txn_execution: bool,
39+
skip_source_compilation: bool,
3840
filter_condition: FilterCondition,
3941
enable_features: Vec<FeatureFlag>,
4042
disable_features: Vec<FeatureFlag>,
@@ -48,6 +50,8 @@ impl DataCollection {
4850
skip_failed_txns: bool,
4951
skip_publish_txns: bool,
5052
dump_write_set: bool,
53+
skip_txn_execution: bool,
54+
skip_source_compilation: bool,
5155
skip_source_code: bool,
5256
target_account: Option<AccountAddress>,
5357
enable_features: Vec<FeatureFlag>,
@@ -58,6 +62,8 @@ impl DataCollection {
5862
current_dir,
5963
batch_size,
6064
dump_write_set,
65+
skip_txn_execution,
66+
skip_source_compilation,
6167
filter_condition: FilterCondition {
6268
skip_failed_txns,
6369
skip_publish_txns,
@@ -76,6 +82,8 @@ impl DataCollection {
7682
skip_failed_txns: bool,
7783
skip_publish_txns: bool,
7884
dump_write_set: bool,
85+
skip_txn_execution: bool,
86+
skip_source_compilation: bool,
7987
skip_source_code: bool,
8088
target_account: Option<AccountAddress>,
8189
enable_features: Vec<FeatureFlag>,
@@ -88,6 +96,8 @@ impl DataCollection {
8896
skip_failed_txns,
8997
skip_publish_txns,
9098
dump_write_set,
99+
skip_txn_execution,
100+
skip_source_compilation,
91101
skip_source_code,
92102
target_account,
93103
enable_features,
@@ -128,6 +138,7 @@ impl DataCollection {
128138
compilation_cache: &mut CompilationCache,
129139
current_dir: PathBuf,
130140
base_experiments: &[String],
141+
skip_source_compilation: bool,
131142
) -> Option<PackageInfo> {
132143
let upgrade_number = if is_aptos_package(&package_name) {
133144
None
@@ -160,6 +171,7 @@ impl DataCollection {
160171
None,
161172
base_experiments,
162173
&[],
174+
skip_source_compilation,
163175
);
164176
if let Err(err) = res {
165177
eprintln!("{} at: {}", err, version);
@@ -205,12 +217,16 @@ impl DataCollection {
205217
return Err(anyhow::Error::msg("aptos packages are missing"));
206218
}
207219
let mut compiled_cache = CompilationCache::default();
208-
compile_aptos_packages(
209-
&aptos_commons_path,
210-
&mut compiled_cache.base_compiled_package_cache,
211-
&base_experiments,
212-
"base",
213-
)?;
220+
// The compiled framework is only injected into the state view for txn
221+
// execution; source-only collection does not need it.
222+
if !self.skip_txn_execution {
223+
compile_aptos_packages(
224+
&aptos_commons_path,
225+
&mut compiled_cache.base_compiled_package_cache,
226+
&base_experiments,
227+
"base",
228+
)?;
229+
}
214230
let compilation_cache: Arc<Mutex<CompilationCache>> = Arc::new(Mutex::new(compiled_cache));
215231
let data_manager = Arc::new(Mutex::new(DataManager::new_with_dir_creation(
216232
&self.current_dir,
@@ -253,40 +269,52 @@ impl DataCollection {
253269
let data_manager = data_manager.clone();
254270
let index = index_writer.clone();
255271
let base_experiments = base_experiments.clone();
256-
let data_state = InMemoryStateStore::default();
257-
let features_to_enable = self.enable_features.clone();
258-
let features_to_disable = self.disable_features.clone();
259-
let cache_v1 = compilation_cache
260-
.lock()
261-
.unwrap()
262-
.base_compiled_package_cache
263-
.clone();
264-
add_aptos_packages_to_state_store(&data_state, &cache_v1);
265-
let state_view = DataStateView::new_with_data_reads_and_code(
266-
self.debugger.clone(),
267-
version,
268-
data_state,
269-
features_to_enable,
270-
features_to_disable,
271-
);
272+
let skip_source_compilation = self.skip_source_compilation;
273+
// Source-only collection skips execution, so it needs no
274+
// state view (and none of its remote state reads).
275+
let state_view_opt = if self.skip_txn_execution {
276+
None
277+
} else {
278+
let data_state = InMemoryStateStore::default();
279+
let features_to_enable = self.enable_features.clone();
280+
let features_to_disable = self.disable_features.clone();
281+
let cache_v1 = compilation_cache
282+
.lock()
283+
.unwrap()
284+
.base_compiled_package_cache
285+
.clone();
286+
add_aptos_packages_to_state_store(&data_state, &cache_v1);
287+
Some(DataStateView::new_with_data_reads_and_code(
288+
self.debugger.clone(),
289+
version,
290+
data_state,
291+
features_to_enable,
292+
features_to_disable,
293+
))
294+
};
272295

273296
let txn_execution_thread = tokio::task::spawn_blocking(move || {
274-
// Use default info to improve performance
275-
let aux_info = PersistedAuxiliaryInfo::None;
297+
let epoch_result_opt = if let Some(state_view) = &state_view_opt {
298+
// Use default info to improve performance
299+
let aux_info = PersistedAuxiliaryInfo::None;
276300

277-
let epoch_result_res =
278-
Self::execute_transactions_at_version_with_state_view(
301+
match Self::execute_transactions_at_version_with_state_view(
279302
vec![txn.clone()],
280303
vec![aux_info],
281-
&state_view,
282-
);
283-
if let Err(err) = epoch_result_res {
284-
println!(
285-
"execution error during transaction at version:{} :{}",
286-
version, err
287-
);
288-
return;
289-
}
304+
state_view,
305+
) {
306+
Ok(outputs) => Some(outputs),
307+
Err(err) => {
308+
println!(
309+
"execution error during transaction at version:{} :{}",
310+
version, err
311+
);
312+
return;
313+
},
314+
}
315+
} else {
316+
None
317+
};
290318

291319
let mut version_idx = TxnIndex {
292320
version,
@@ -304,21 +332,26 @@ impl DataCollection {
304332
&mut compilation_cache.lock().unwrap(),
305333
current_dir.clone(),
306334
&base_experiments,
335+
skip_source_compilation,
307336
);
308337
if package_info_opt.is_none() {
309338
return;
310339
}
311340
version_idx.package_info = package_info_opt.unwrap();
312341
}
313342

314-
// dump through data_manager
315-
Self::dump_txn_index(
316-
&mut data_manager.lock().unwrap(),
317-
version_idx,
318-
&state_view.get_state_keys().lock().unwrap(),
319-
epoch_result_res,
320-
dump_write_set,
321-
);
343+
// dump through data_manager (skipped in source-only mode)
344+
if let (Some(state_view), Some(outputs)) =
345+
(state_view_opt, epoch_result_opt)
346+
{
347+
Self::dump_txn_index(
348+
&mut data_manager.lock().unwrap(),
349+
version_idx,
350+
&state_view.get_state_keys().lock().unwrap(),
351+
Ok(outputs),
352+
dump_write_set,
353+
);
354+
}
322355

323356
// Log version
324357
index.lock().unwrap().add_version(version);

aptos-move/aptos-e2e-comparison-testing/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@ struct CompilationCache {
376376
failed_packages_compared: HashSet<PackageInfo>,
377377
base_compiled_package_cache: HashMap<PackageInfo, HashMap<ModuleId, Vec<u8>>>,
378378
compared_compiled_package_cache: HashMap<PackageInfo, HashMap<ModuleId, Vec<u8>>>,
379+
/// Packages whose source has been written to disk; used to avoid re-dumping
380+
/// when compilation (and thus `compiled_package_map`) is skipped.
381+
dumped_packages: HashSet<PackageInfo>,
379382
}
380383

381384
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Hash)]
@@ -501,7 +504,11 @@ fn dump_and_compile_from_package_metadata(
501504
execution_mode: Option<ExecutionMode>,
502505
base_experiments: &[String],
503506
compared_experiments: &[String],
507+
skip_source_compilation: bool,
504508
) -> anyhow::Result<()> {
509+
if skip_source_compilation && compilation_cache.dumped_packages.contains(&package_info) {
510+
return Ok(());
511+
}
505512
let root_package_dir = root_dir.join(format!("{}", package_info,));
506513
if compilation_cache
507514
.failed_packages_base
@@ -603,6 +610,7 @@ fn dump_and_compile_from_package_metadata(
603610
execution_mode,
604611
base_experiments,
605612
compared_experiments,
613+
skip_source_compilation,
606614
)?;
607615
}
608616
break;
@@ -613,8 +621,14 @@ fn dump_and_compile_from_package_metadata(
613621
// step 4: dump the fixed manifest file
614622
let toml_path = root_package_dir.join("Move.toml");
615623
std::fs::write(toml_path, manifest.to_string()).unwrap();
624+
compilation_cache
625+
.dumped_packages
626+
.insert(package_info.clone());
616627

617628
// step 5: test whether the code can be compiled
629+
if skip_source_compilation {
630+
return Ok(());
631+
}
618632
if !compilation_cache
619633
.compiled_package_map
620634
.contains_key(&package_info)

aptos-move/aptos-e2e-comparison-testing/src/main.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ pub enum Cmd {
3838
/// Dump the write set of txns
3939
#[clap(long, default_value_t = false)]
4040
dump_write_set: bool,
41+
/// Only collect source code: skip txn execution and do not dump
42+
/// state data, write sets or the txn index
43+
#[clap(long, default_value_t = false)]
44+
skip_txn_execution: bool,
45+
/// Do not compile the dumped source code to validate it; sources are
46+
/// still written to disk. Speeds up source-only collection considerably
47+
#[clap(long, default_value_t = false)]
48+
skip_source_compilation: bool,
4149
/// With this set, only dump transactions that are sent to this account
4250
#[clap(long)]
4351
target_account: Option<AccountAddress>,
@@ -161,6 +169,8 @@ async fn main() -> Result<()> {
161169
skip_publish_txns,
162170
skip_source_code_check: skip_source_code,
163171
dump_write_set,
172+
skip_txn_execution,
173+
skip_source_compilation,
164174
target_account,
165175
} => {
166176
let batch_size = BATCH_SIZE;
@@ -187,6 +197,8 @@ async fn main() -> Result<()> {
187197
skip_failed_txns,
188198
skip_publish_txns,
189199
dump_write_set,
200+
skip_txn_execution,
201+
skip_source_compilation,
190202
skip_source_code,
191203
target_account,
192204
args.enable_features,

aptos-move/aptos-e2e-comparison-testing/src/online_execution.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ impl OnlineExecutor {
125125
execution_mode,
126126
base_experiments,
127127
compared_experiments,
128+
false,
128129
);
129130
if let Err(err) = res {
130131
eprintln!("{} at:{}", err, version);

aptos-move/aptos-validator-interface/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ async-recursion = { workspace = true }
2525
async-trait = { workspace = true }
2626
bcs = { workspace = true }
2727
bytes = { workspace = true }
28+
futures = { workspace = true }
2829
lru = { workspace = true }
2930
move-core-types = { workspace = true }
3031
tokio = { workspace = true }

aptos-move/aptos-validator-interface/src/rest_interface.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,54 @@ impl RestDebuggerInterface {
3030
pub fn new(client: Client) -> Self {
3131
Self(client)
3232
}
33+
34+
/// Fetches transactions and their infos for `[start, start + limit)`, requesting the
35+
/// 100-txn API pages concurrently. Unlike [`AptosValidatorInterface::get_committed_transactions`],
36+
/// this skips fetching persisted auxiliary infos, which the filtering path does not use.
37+
async fn get_committed_transactions_no_aux(
38+
&self,
39+
start: Version,
40+
limit: u64,
41+
) -> Result<(Vec<Transaction>, Vec<TransactionInfo>)> {
42+
const PAGE_SIZE: u64 = 100;
43+
let mut chunk_futures = vec![];
44+
let mut cursor = start;
45+
while cursor < start + limit {
46+
let count = PAGE_SIZE.min(start + limit - cursor);
47+
let client = self.0.clone();
48+
chunk_futures.push(async move {
49+
let mut chunk = Vec::with_capacity(count as usize);
50+
while (chunk.len() as u64) < count {
51+
let page = client
52+
.get_transactions_bcs(
53+
Some(cursor + chunk.len() as u64),
54+
Some((count - chunk.len() as u64) as u16),
55+
)
56+
.await?
57+
.into_inner();
58+
if page.is_empty() {
59+
return Err(anyhow!(
60+
"no transactions returned at version {}",
61+
cursor + chunk.len() as u64
62+
));
63+
}
64+
chunk.extend(page);
65+
}
66+
Ok(chunk)
67+
});
68+
cursor += count;
69+
}
70+
let mut txns = Vec::with_capacity(limit as usize);
71+
let mut txn_infos = Vec::with_capacity(limit as usize);
72+
for chunk in futures::future::join_all(chunk_futures).await {
73+
for txn in chunk? {
74+
txns.push(txn.transaction);
75+
txn_infos.push(txn.info);
76+
}
77+
}
78+
println!("Got {}/{} txns from RestApi.", txns.len(), limit);
79+
Ok((txns, txn_infos))
80+
}
3381
}
3482

3583
#[async_recursion]
@@ -276,7 +324,7 @@ impl AptosValidatorInterface for RestDebuggerInterface {
276324
)>,
277325
> {
278326
let mut txns = Vec::with_capacity(limit as usize);
279-
let (tns, infos, _auxiliary_infos) = self.get_committed_transactions(start, limit).await?;
327+
let (tns, infos) = self.get_committed_transactions_no_aux(start, limit).await?;
280328
let temp_txns = tns
281329
.iter()
282330
.zip(infos)

0 commit comments

Comments
 (0)