Skip to content

Commit 4b9d2b7

Browse files
[vm] Remove V1 aggregator from execution
Fold AggregatorV1 changes into the same write ops the VM already uses for V2 delayed fields, instead of bespoke variants. A flag-off delta is a Write flagged is_aggregator_v1_delta; a flag-on delta is an InPlaceDelayedFieldChange; a read, create, or delete is a WriteWithDelayedFields. Squashing, fee exclusion, and the in-place id exchange now reuse the V2 paths, removing the AggregatorV1Delta and AggregatorV1MaterializedDelta variants and their squash arms, along with the dormant V1 DeltaOp machinery in the block executor and mvhashmap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent ee3597b commit 4b9d2b7

49 files changed

Lines changed: 919 additions & 3241 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

aptos-move/aptos-aggregator/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ claims = { workspace = true }
2323
move-binary-format = { workspace = true }
2424
move-core-types = { workspace = true }
2525
move-vm-types = { workspace = true }
26+
once_cell = { workspace = true }
2627
triomphe = { workspace = true }
2728

2829
[dev-dependencies]
29-
once_cell = { workspace = true }
3030
test-case = { workspace = true }

aptos-move/aptos-aggregator/src/aggregator_v1_extension.rs

Lines changed: 122 additions & 534 deletions
Large diffs are not rendered by default.

aptos-move/aptos-aggregator/src/delta_change_set.rs

Lines changed: 1 addition & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -211,26 +211,7 @@ pub fn delta_add(v: u128, max_value: u128) -> DeltaOp {
211211
#[cfg(test)]
212212
mod test {
213213
use super::*;
214-
use crate::{
215-
aggregator_v1_extension::{EADD_OVERFLOW, ESUB_UNDERFLOW},
216-
resolver::{TAggregatorV1View, TDelayedFieldView},
217-
types::DelayedFieldValue,
218-
FakeAggregatorView,
219-
};
220-
use aptos_types::{
221-
error::PanicError,
222-
state_store::{
223-
state_key::StateKey,
224-
state_value::{StateValue, StateValueMetadata},
225-
},
226-
write_set::WriteOp,
227-
};
228-
use claims::{assert_err, assert_none, assert_ok, assert_ok_eq, assert_some_eq};
229-
use move_binary_format::errors::{PartialVMError, PartialVMResult};
230-
use move_core_types::{value::MoveTypeLayout, vm_status::StatusCode};
231-
use once_cell::sync::Lazy;
232-
use std::collections::{BTreeMap, HashSet};
233-
use triomphe::Arc as TriompheArc;
214+
use claims::{assert_err, assert_ok, assert_ok_eq};
234215

235216
fn delta_add_with_history(v: u128, max_value: u128, max: u128, min: u128) -> DeltaOp {
236217
let mut delta = delta_add(v, max_value);
@@ -472,142 +453,4 @@ mod test {
472453
assert_eq!(b, c);
473454
assert_eq!(b.update, Negative(1));
474455
}
475-
476-
static KEY: Lazy<StateKey> = Lazy::new(|| StateKey::raw(b"test-key"));
477-
478-
#[test]
479-
fn test_failed_write_op_conversion_because_of_empty_storage() {
480-
let state_view = FakeAggregatorView::default();
481-
let delta_op = delta_add(10, 1000);
482-
483-
let err =
484-
assert_err!(state_view.try_convert_aggregator_v1_delta_into_write_op(&KEY, &delta_op));
485-
assert_eq!(
486-
err.major_status(),
487-
StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR
488-
);
489-
assert_none!(err.sub_status());
490-
}
491-
492-
struct BadStorage;
493-
494-
impl TAggregatorV1View for BadStorage {
495-
type Identifier = StateKey;
496-
497-
fn get_aggregator_v1_state_value(
498-
&self,
499-
_id: &Self::Identifier,
500-
) -> PartialVMResult<Option<StateValue>> {
501-
Err(
502-
PartialVMError::new(StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR)
503-
.with_message("Error message from BadStorage.".to_string()),
504-
)
505-
}
506-
}
507-
508-
impl TDelayedFieldView for BadStorage {
509-
type Identifier = ();
510-
type ResourceGroupTag = ();
511-
type ResourceKey = ();
512-
513-
fn get_delayed_field_value(
514-
&self,
515-
_id: &Self::Identifier,
516-
) -> Result<DelayedFieldValue, PanicOr<DelayedFieldsSpeculativeError>> {
517-
Err(code_invariant_error("Error message from BadStorage.").into())
518-
}
519-
520-
fn delayed_field_try_add_delta_outcome(
521-
&self,
522-
_id: &Self::Identifier,
523-
_base_delta: &SignedU128,
524-
_delta: &SignedU128,
525-
_max_value: u128,
526-
) -> Result<bool, PanicOr<DelayedFieldsSpeculativeError>> {
527-
Err(code_invariant_error("Error message from BadStorage.").into())
528-
}
529-
530-
fn generate_delayed_field_id(&self, _width: u32) -> Self::Identifier {
531-
unimplemented!("Irrelevant for the test")
532-
}
533-
534-
fn validate_delayed_field_id(&self, _id: &Self::Identifier) -> Result<(), PanicError> {
535-
unimplemented!("Irrelevant for the test")
536-
}
537-
538-
fn get_reads_needing_exchange(
539-
&self,
540-
_delayed_write_set_keys: &HashSet<Self::Identifier>,
541-
_skip: &HashSet<Self::ResourceKey>,
542-
) -> Result<
543-
BTreeMap<Self::ResourceKey, (StateValueMetadata, u64, TriompheArc<MoveTypeLayout>)>,
544-
PanicError,
545-
> {
546-
unimplemented!("Irrelevant for the test")
547-
}
548-
549-
fn get_group_reads_needing_exchange(
550-
&self,
551-
_delayed_write_set_keys: &HashSet<Self::Identifier>,
552-
_skip: &HashSet<Self::ResourceKey>,
553-
) -> PartialVMResult<BTreeMap<Self::ResourceKey, (StateValueMetadata, u64)>> {
554-
unimplemented!("Irrelevant for the test")
555-
}
556-
}
557-
558-
#[test]
559-
fn test_failed_write_op_conversion_because_of_speculative_error() {
560-
let state_view = BadStorage;
561-
let delta_op = delta_add(10, 1000);
562-
563-
let err =
564-
assert_err!(state_view.try_convert_aggregator_v1_delta_into_write_op(&KEY, &delta_op));
565-
assert_eq!(
566-
err.major_status(),
567-
StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR
568-
);
569-
assert_none!(err.sub_status());
570-
}
571-
572-
#[test]
573-
fn test_successful_write_op_conversion() {
574-
let mut state_view = FakeAggregatorView::default();
575-
state_view.set_from_state_key(KEY.clone(), 100);
576-
577-
// Both addition and subtraction should succeed!
578-
let add_op = delta_add(100, 200);
579-
let sub_op = delta_sub(100, 200);
580-
581-
let add_result = state_view.try_convert_aggregator_v1_delta_into_write_op(&KEY, &add_op);
582-
assert_ok_eq!(
583-
add_result,
584-
WriteOp::legacy_modification(serialize(&200).into())
585-
);
586-
587-
let sub_result = state_view.try_convert_aggregator_v1_delta_into_write_op(&KEY, &sub_op);
588-
assert_ok_eq!(
589-
sub_result,
590-
WriteOp::legacy_modification(serialize(&0).into())
591-
);
592-
}
593-
594-
#[test]
595-
fn test_unsuccessful_write_op_conversion() {
596-
let mut state_view = FakeAggregatorView::default();
597-
state_view.set_from_state_key(KEY.clone(), 100);
598-
599-
// Both addition and subtraction should fail!
600-
let add_op = delta_add(15, 100);
601-
let sub_op = delta_sub(101, 1000);
602-
603-
let err =
604-
assert_err!(state_view.try_convert_aggregator_v1_delta_into_write_op(&KEY, &add_op));
605-
assert_eq!(err.major_status(), StatusCode::ABORTED);
606-
assert_some_eq!(err.sub_status(), EADD_OVERFLOW);
607-
608-
let err =
609-
assert_err!(state_view.try_convert_aggregator_v1_delta_into_write_op(&KEY, &sub_op));
610-
assert_eq!(err.major_status(), StatusCode::ABORTED);
611-
assert_some_eq!(err.sub_status(), ESUB_UNDERFLOW);
612-
}
613456
}

aptos-move/aptos-aggregator/src/resolver.rs

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,16 @@
22
// Licensed pursuant to the Innovation-Enabling Source Code License, available at https://github.com/aptos-labs/aptos-core/blob/main/LICENSE
33

44
use crate::{
5-
aggregator_v1_extension::{addition_v1_error, subtraction_v1_error},
65
bounded_math::SignedU128,
7-
delta_change_set::{serialize, DeltaOp},
8-
types::{DelayedFieldValue, DelayedFieldsSpeculativeError, DeltaApplicationFailureReason},
6+
types::{DelayedFieldValue, DelayedFieldsSpeculativeError},
97
};
108
use aptos_types::{
11-
error::{code_invariant_error, PanicError, PanicOr},
9+
error::{PanicError, PanicOr},
1210
state_store::{
1311
state_key::StateKey,
1412
state_value::{StateValue, StateValueMetadata},
1513
StateView,
1614
},
17-
write_set::WriteOp,
1815
};
1916
use move_binary_format::errors::{PartialVMError, PartialVMResult};
2017
use move_core_types::{language_storage::StructTag, value::MoveTypeLayout, vm_status::StatusCode};
@@ -38,6 +35,9 @@ pub trait TAggregatorV1View {
3835
/// - Ok(Some(...)) if aggregator value exists in storage,
3936
/// - Err(...) otherwise (e.g. storage error or failed delta
4037
/// application).
38+
///
39+
/// Used when delayed field optimization is not enabled (implementation is
40+
/// sequential).
4141
fn get_aggregator_v1_state_value(
4242
&self,
4343
id: &Self::Identifier,
@@ -60,49 +60,20 @@ pub trait TAggregatorV1View {
6060
&self,
6161
id: &Self::Identifier,
6262
) -> PartialVMResult<Option<StateValueMetadata>> {
63-
// When getting state value metadata for aggregator V1, we need to do a
64-
// precise read.
6563
let maybe_state_value = self.get_aggregator_v1_state_value(id)?;
6664
Ok(maybe_state_value.map(StateValue::into_metadata))
6765
}
6866

69-
fn get_aggregator_v1_state_value_size(
70-
&self,
71-
id: &Self::Identifier,
72-
) -> PartialVMResult<Option<u64>> {
73-
let maybe_state_value = self.get_aggregator_v1_state_value(id)?;
74-
Ok(maybe_state_value.map(|v| v.size() as u64))
75-
}
76-
77-
/// Consumes a single delta of aggregator V1, and tries to materialize it
78-
/// with a given identifier (state key). If materialization succeeds, a
79-
/// write op is produced.
80-
fn try_convert_aggregator_v1_delta_into_write_op(
67+
/// Used **ONLY** if delayed field optimization is enabled.
68+
///
69+
/// Returns an ID corresponding to the exchanged value of the aggregator.
70+
fn get_aggregator_v1_delayed_field_id(
8171
&self,
82-
id: &Self::Identifier,
83-
delta_op: &DeltaOp,
84-
) -> PartialVMResult<WriteOp> {
85-
let base = self.get_aggregator_v1_value(id)?.ok_or_else(|| {
86-
PartialVMError::new(StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR)
87-
.with_message("Cannot convert delta for deleted aggregator".to_string())
88-
})?;
89-
delta_op
90-
.apply_to(base)
91-
.map_err(|e| match &e {
92-
PanicOr::Or(DelayedFieldsSpeculativeError::DeltaApplication {
93-
reason: DeltaApplicationFailureReason::Overflow,
94-
..
95-
}) => addition_v1_error(e),
96-
PanicOr::Or(DelayedFieldsSpeculativeError::DeltaApplication {
97-
reason: DeltaApplicationFailureReason::Underflow,
98-
..
99-
}) => subtraction_v1_error(e),
100-
// Because aggregator V1 never underflows or overflows, all other
101-
// application errors are bugs.
102-
_ => code_invariant_error(format!("Unexpected delta application error: {:?}", e))
103-
.into(),
104-
})
105-
.map(|result| WriteOp::legacy_modification(serialize(&result).into()))
72+
_id: &Self::Identifier,
73+
) -> PartialVMResult<Option<DelayedFieldID>> {
74+
// By default - there is no ID (optimization not enabled). Callers
75+
// handle this case as an error gracefully.
76+
Ok(None)
10677
}
10778
}
10879

aptos-move/aptos-debugger/src/bin/remote-gas-profiler.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ async fn main() -> Result<()> {
6767
gas_log.exec_io.check_consistency()?;
6868
gas_log.storage.check_consistency()?;
6969

70-
let txn_output =
71-
output.try_materialize_into_transaction_output(&debugger.state_view_at_version(version))?;
70+
let txn_output = output.try_materialize_into_transaction_output()?;
7271

7372
// Show results to the user
7473
println!("{:#?}", txn_output);

aptos-move/aptos-release-builder/src/simulate.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,8 @@ fn force_end_epoch(state_view: &impl SimulationStateStore) -> Result<()> {
347347
&mut TraversalContext::new(&traversal_storage),
348348
&module_storage,
349349
)?;
350-
let mut change_set = sess.finish(&change_set_configs, &module_storage)?;
350+
let change_set = sess.finish(&change_set_configs, &module_storage)?;
351351

352-
change_set.try_materialize_aggregator_v1_delta_set(&resolver)?;
353352
let (write_set, _events) = change_set
354353
.try_combine_into_storage_change_set(ModuleWriteSet::empty())
355354
.expect("Failed to convert to storage ChangeSet")
@@ -530,7 +529,7 @@ pub async fn simulate_multistep_proposal(
530529
);
531530

532531
let txn_output = vm_output
533-
.try_materialize_into_transaction_output(&resolver)
532+
.try_materialize_into_transaction_output()
534533
.context("failed to materialize transaction output")?;
535534

536535
let txn_status = txn_output.status();

aptos-move/aptos-transaction-simulation-session/src/session.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ impl Session {
549549
);
550550
}
551551

552-
let txn_output = vm_output.try_materialize_into_transaction_output(&resolver)?;
552+
let txn_output = vm_output.try_materialize_into_transaction_output()?;
553553
self.state_store.apply_write_set(txn_output.write_set())?;
554554

555555
// Re-patch the randomness seed. The block prologue clears it because our
@@ -612,7 +612,7 @@ impl Session {
612612
&AuxiliaryInfo::new_timestamp_not_yet_assigned(0),
613613
)
614614
.map_err(|e| anyhow::anyhow!("transaction execution failed: {:?}", e))?;
615-
let txn_output = vm_output.try_materialize_into_transaction_output(&resolver)?;
615+
let txn_output = vm_output.try_materialize_into_transaction_output()?;
616616
// `finish` panics on a consistency failure with the library's generic
617617
// bug-report message; `finish_without_consistency_check` skips the
618618
// check entirely. User-facing tools that want a custom error (or to
@@ -632,7 +632,7 @@ impl Session {
632632
&log_context,
633633
&AuxiliaryInfo::new_timestamp_not_yet_assigned(0),
634634
);
635-
let txn_output = vm_output.try_materialize_into_transaction_output(&resolver)?;
635+
let txn_output = vm_output.try_materialize_into_transaction_output()?;
636636
(vm_status, txn_output, None)
637637
};
638638

0 commit comments

Comments
 (0)