Skip to content

Commit

Permalink
track storage slot payer
Browse files Browse the repository at this point in the history
  • Loading branch information
msmouse committed Feb 8, 2023
1 parent 6bc22ce commit f1ecc6f
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 41 deletions.
4 changes: 2 additions & 2 deletions aptos-move/aptos-gas/src/transaction/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,11 @@ impl ChangeSetConfigs {
}
}

pub fn resource_creation_as_modification(&self) -> bool {
pub fn legacy_resource_creation_as_modification(&self) -> bool {
// Bug fixed at gas_feature_version 3 where (non-group) resource creation was converted to
// modification.
// Modules and table items were not affected (https://github.com/aptos-labs/aptos-core/pull/4722/commits/7c5e52297e8d1a6eac67a68a804ab1ca2a0b0f37).
// Resource groups were not affected because they were
// Resource groups and state values with metadata were not affected because they were
// introduced later than feature_version 3 on all networks.
self.gas_feature_version < 3
}
Expand Down
18 changes: 13 additions & 5 deletions aptos-move/aptos-vm/src/data_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
// SPDX-License-Identifier: Apache-2.0
//! Scratchpad for on chain values during the execution.
use crate::move_vm_ext::MoveResolverExt;
use crate::move_vm_ext::{MoveResolverExt, MoveVmExt};
#[allow(unused_imports)]
use anyhow::Error;
use aptos_framework::{natives::state_storage::StateStorageUsageResolver, RuntimeModuleMetadataV1};
use aptos_state_view::StateView;
use aptos_types::{
access_path::AccessPath,
on_chain_config::ConfigStorage,
on_chain_config::{ConfigStorage, CurrentTimeMicroseconds},
state_store::{state_key::StateKey, state_storage_usage::StateStorageUsage},
};
use move_binary_format::{errors::*, CompiledModule};
Expand All @@ -20,21 +20,29 @@ use move_core_types::{
vm_status::StatusCode,
};
use move_table_extension::{TableHandle, TableResolver};
use move_vm_runtime::move_vm::MoveVM;
use std::ops::{Deref, DerefMut};

pub struct MoveResolverWithVMMetadata<'a, 'm, S> {
move_resolver: &'a S,
move_vm: &'m MoveVM,
move_vm: &'m MoveVmExt,
}

impl<'a, 'm, S: MoveResolverExt> MoveResolverWithVMMetadata<'a, 'm, S> {
pub fn new(move_resolver: &'a S, move_vm: &'m MoveVM) -> Self {
pub fn new(move_resolver: &'a S, move_vm: &'m MoveVmExt) -> Self {
Self {
move_resolver,
move_vm,
}
}

pub fn vm(&self) -> &MoveVmExt {
self.move_vm
}

pub fn current_time(&self) -> Option<CurrentTimeMicroseconds> {
todo!()
// CurrentTimeMicroseconds::fetch_config(self.move_resolver.)
}
}

impl<'a, 'm, S: MoveResolverExt> MoveResolverExt for MoveResolverWithVMMetadata<'a, 'm, S> {
Expand Down
145 changes: 112 additions & 33 deletions aptos-move/aptos-vm/src/move_vm_ext/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{
access_path_cache::AccessPathCache, data_cache::MoveResolverWithVMMetadata,
move_vm_ext::MoveResolverExt, transaction_metadata::TransactionMetadata,
access_path_cache::AccessPathCache,
data_cache::MoveResolverWithVMMetadata,
move_vm_ext::{MoveResolverExt, MoveVmExt},
transaction_metadata::TransactionMetadata,
};
use aptos_aggregator::{
aggregator_extension::AggregatorID,
Expand All @@ -20,7 +22,8 @@ use aptos_gas::ChangeSetConfigs;
use aptos_types::{
block_metadata::BlockMetadata,
contract_event::ContractEvent,
state_store::{state_key::StateKey, table::TableHandle},
on_chain_config::{Features, OnChainConfig},
state_store::{state_key::StateKey, state_value::StateValueMetadata, table::TableHandle},
transaction::{ChangeSet, SignatureCheckedTransaction},
write_set::{WriteOp, WriteSetMut},
};
Expand All @@ -34,7 +37,7 @@ use move_core_types::{
vm_status::{StatusCode, VMStatus},
};
use move_table_extension::{NativeTableContext, TableChangeSet};
use move_vm_runtime::{move_vm::MoveVM, session::Session};
use move_vm_runtime::session::Session;
use serde::{Deserialize, Serialize};
use std::{
collections::BTreeMap,
Expand Down Expand Up @@ -91,21 +94,35 @@ impl SessionId {
pub fn as_uuid(&self) -> HashValue {
self.hash()
}

pub fn sender(&self) -> Option<AccountAddress> {
match self {
SessionId::Txn { sender, .. } => Some(*sender),
SessionId::BlockMeta { .. } | SessionId::Genesis { .. } | SessionId::Void => None,
}
}
}

pub struct SessionExt<'r, 'l, S> {
inner: Session<'r, 'l, S>,
remote: MoveResolverWithVMMetadata<'r, 'l, S>,
new_slot_payer: Option<AccountAddress>,
}

impl<'r, 'l, S> SessionExt<'r, 'l, S>
where
S: MoveResolverExt + 'r,
{
pub fn new(inner: Session<'r, 'l, S>, move_vm: &'l MoveVM, remote: &'r S) -> Self {
pub fn new(
inner: Session<'r, 'l, S>,
move_vm: &'l MoveVmExt,
remote: &'r S,
new_slot_payer: Option<AccountAddress>,
) -> Self {
Self {
inner,
remote: MoveResolverWithVMMetadata::new(remote, move_vm),
new_slot_payer,
}
}

Expand All @@ -127,6 +144,8 @@ where
let aggregator_change_set = aggregator_context.into_change_set();

Self::convert_change_set(
&self.remote,
self.new_slot_payer,
change_set,
resource_group_change_set,
events,
Expand Down Expand Up @@ -254,6 +273,8 @@ where
}

pub fn convert_change_set<C: AccessPathCache>(
remote: &MoveResolverWithVMMetadata<S>,
new_slot_payer: Option<AccountAddress>,
change_set: MoveChangeSet,
resource_group_change_set: MoveChangeSet,
events: Vec<MoveEvent>,
Expand All @@ -264,21 +285,40 @@ where
) -> Result<ChangeSetExt, VMStatus> {
let mut write_set_mut = WriteSetMut::new(Vec::new());
let mut delta_change_set = DeltaChangeSet::empty();
let mut new_slot_metadata: Option<StateValueMetadata> = None;
// Features can change in the same block or transaction, better load it with the latest view
// than passing it down from the beginning of the session.
if Features::fetch_config(remote).map_or(false, |features| {
features.is_storage_slot_metadata_enabled()
}) {
if let Some(payer) = new_slot_payer {
if let Some(current_time) = remote.current_time() {
new_slot_metadata = Some(StateValueMetadata::new(payer, 0, &current_time));
}
}
}
let woc = WriteOpConverter {
remote,
new_slot_metadata,
};

for (addr, account_changeset) in change_set.into_inner() {
let (modules, resources) = account_changeset.into_inner();
for (struct_tag, blob_op) in resources {
let state_key = StateKey::AccessPath(ap_cache.get_resource_path(addr, struct_tag));
let op =
Self::convert_write_op(blob_op, configs.resource_creation_as_modification());
let op = woc.convert(
&state_key,
blob_op,
configs.legacy_resource_creation_as_modification(),
)?;

write_set_mut.insert((state_key, op))
}

for (name, blob_op) in modules {
let state_key =
StateKey::AccessPath(ap_cache.get_module_path(ModuleId::new(addr, name)));
let op = Self::convert_write_op(blob_op, false);

let op = woc.convert(&state_key, blob_op, false)?;
write_set_mut.insert((state_key, op))
}
}
Expand All @@ -288,15 +328,15 @@ where
for (struct_tag, blob_op) in resources {
let state_key =
StateKey::AccessPath(ap_cache.get_resource_group_path(addr, struct_tag));
let op = Self::convert_write_op(blob_op, false);
let op = woc.convert(&state_key, blob_op, false)?;
write_set_mut.insert((state_key, op))
}
}

for (handle, change) in table_change_set.changes {
for (key, value_op) in change.entries {
let state_key = StateKey::table_item(handle.into(), key);
let op = Self::convert_write_op(value_op, false);
let op = woc.convert(&state_key, value_op, false)?;
write_set_mut.insert((state_key, op))
}
}
Expand All @@ -308,12 +348,13 @@ where

match change {
AggregatorChange::Write(value) => {
let write_op = WriteOp::Modification(serialize(&value));
let write_op =
woc.convert(&state_key, MoveStorageOp::Modify(serialize(&value)), false)?;
write_set_mut.insert((state_key, write_op));
},
AggregatorChange::Merge(delta_op) => delta_change_set.insert((state_key, delta_op)),
AggregatorChange::Delete => {
let write_op = WriteOp::Deletion;
let write_op = woc.convert(&state_key, MoveStorageOp::Delete, false)?;
write_set_mut.insert((state_key, write_op));
},
}
Expand All @@ -339,26 +380,6 @@ where
Arc::new(configs.clone()),
))
}

fn convert_write_op(
move_storage_op: MoveStorageOp<Vec<u8>>,
creation_as_modification: bool,
) -> WriteOp {
use MoveStorageOp::*;
use WriteOp::*;

match move_storage_op {
Delete => Deletion,
New(blob) => {
if creation_as_modification {
Modification(blob)
} else {
Creation(blob)
}
},
Modify(blob) => Modification(blob),
}
}
}

impl<'r, 'l, S> Deref for SessionExt<'r, 'l, S> {
Expand All @@ -374,3 +395,61 @@ impl<'r, 'l, S> DerefMut for SessionExt<'r, 'l, S> {
&mut self.inner
}
}

struct WriteOpConverter<'r, 'l, S> {
remote: &'r MoveResolverWithVMMetadata<'r, 'l, S>,
new_slot_metadata: Option<StateValueMetadata>,
}

impl<'r, 'l, S: MoveResolverExt> WriteOpConverter<'r, 'l, S> {
fn convert(
&self,
state_key: &StateKey,
move_storage_op: MoveStorageOp<Vec<u8>>,
legacy_creation_as_modification: bool,
) -> Result<WriteOp, VMStatus> {
use MoveStorageOp::*;
use WriteOp::*;

let existing_value_opt = self
.remote
.get_state_value(state_key)
.map_err(|_| VMStatus::Error(StatusCode::STORAGE_ERROR))?;

let write_op = match (existing_value_opt, move_storage_op) {
(None, Modify(_) | Delete) | (Some(_), New(_)) => {
return Err(VMStatus::Error(
StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR,
))
},
(None, New(data)) => match &self.new_slot_metadata {
None => {
if legacy_creation_as_modification {
Modification(data)
} else {
Creation(data)
}
},
Some(metadata) => CreationWithMetadata {
data,
metadata: metadata.clone(),
},
},
(Some(existing_value), Modify(data)) => {
// Inherit metadata even if the feature flags is turned off, for compatibility.
match existing_value.into_metadata() {
None => Modification(data),
Some(metadata) => ModificationWithMetadata { data, metadata },
}
},
(Some(existing_value), Delete) => {
// Inherit metadata even if the feature flags is turned off, for compatibility.
match existing_value.into_metadata() {
None => Deletion,
Some(metadata) => DeletionWithMetadata { metadata },
}
},
};
Ok(write_op)
}
}
8 changes: 8 additions & 0 deletions aptos-move/aptos-vm/src/move_vm_ext/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use std::ops::Deref;
pub struct MoveVmExt {
inner: MoveVM,
chain_id: u8,
features: Features,
}

impl MoveVmExt {
Expand Down Expand Up @@ -59,6 +60,7 @@ impl MoveVmExt {
},
)?,
chain_id,
features,
})
}

Expand All @@ -78,6 +80,7 @@ impl MoveVmExt {
extensions.add(NativeRistrettoPointContext::new());
extensions.add(NativeAggregatorContext::new(txn_hash, remote));

let sender_opt = session_id.sender();
let script_hash = match session_id {
SessionId::Txn {
sender: _,
Expand All @@ -99,8 +102,13 @@ impl MoveVmExt {
self.inner.new_session_with_extensions(remote, extensions),
self,
remote,
sender_opt,
)
}

pub fn features(&self) -> &Features {
&self.features
}
}

impl Deref for MoveVmExt {
Expand Down
4 changes: 4 additions & 0 deletions types/src/on_chain_config/aptos_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ impl Features {
pub fn are_resource_groups_enabled(&self) -> bool {
self.is_enabled(FeatureFlag::RESOURCE_GROUPS)
}

pub fn is_storage_slot_metadata_enabled(&self) -> bool {
self.is_enabled(FeatureFlag::STORAGE_SLOT_METADATA)
}
}

// --------------------------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions types/src/on_chain_config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod aptos_version;
mod chain_id;
mod consensus_config;
mod gas_schedule;
mod timestamp;
mod validator_set;

pub use self::{
Expand All @@ -36,6 +37,7 @@ pub use self::{
ProposerElectionType,
},
gas_schedule::{GasSchedule, GasScheduleV2, StorageGasSchedule},
timestamp::CurrentTimeMicroseconds,
validator_set::{ConsensusScheme, ValidatorSet},
};

Expand Down
15 changes: 15 additions & 0 deletions types/src/on_chain_config/timestamp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::on_chain_config::OnChainConfig;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct CurrentTimeMicroseconds {
pub microseconds: u64,
}

impl OnChainConfig for CurrentTimeMicroseconds {
const MODULE_IDENTIFIER: &'static str = "timestamp";
const TYPE_IDENTIFIER: &'static str = "CurrentTimeMicroseconds";
}
Loading

0 comments on commit f1ecc6f

Please sign in to comment.