Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update StateValueMetadata and reenable metadata tracking on devnet #9480

Merged
merged 3 commits into from
Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions aptos-move/aptos-gas-meter/src/meter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,12 @@ where
.map_err(|e| e.finish(Location::Undefined))
}

fn storage_fee_per_write(&self, key: &StateKey, op: &WriteOp) -> Fee {
self.vm_gas_params().txn.storage_fee_per_write(key, op)
fn storage_fee_for_state_slot(&self, op: &WriteOp) -> Fee {
self.vm_gas_params().txn.storage_fee_for_slot(op)
}

fn storage_fee_for_state_bytes(&self, key: &StateKey, op: &WriteOp) -> Fee {
self.vm_gas_params().txn.storage_fee_for_bytes(key, op)
}

fn storage_fee_per_event(&self, event: &ContractEvent) -> Fee {
Expand Down
53 changes: 42 additions & 11 deletions aptos-move/aptos-gas-meter/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use aptos_gas_schedule::VMGasParameters;
use aptos_types::{
contract_event::ContractEvent, state_store::state_key::StateKey, write_set::WriteOp,
};
use aptos_vm_types::storage::StorageGasParameters;
use aptos_vm_types::{change_set::VMChangeSet, storage::StorageGasParameters};
use move_binary_format::errors::{Location, PartialVMResult, VMResult};
use move_core_types::gas_algebra::{InternalGas, InternalGasUnit, NumBytes};
use move_vm_types::gas::GasMeter as MoveGasMeter;
Expand Down Expand Up @@ -103,8 +103,11 @@ pub trait AptosGasMeter: MoveGasMeter {
/// storage costs.
fn charge_io_gas_for_write(&mut self, key: &StateKey, op: &WriteOp) -> VMResult<()>;

/// Calculates the storage fee for a write operation.
fn storage_fee_per_write(&self, key: &StateKey, op: &WriteOp) -> Fee;
/// Calculates the storage fee for a state slot allocation.
fn storage_fee_for_state_slot(&self, op: &WriteOp) -> Fee;

/// Calculates the storage fee for state bytes.
fn storage_fee_for_state_bytes(&self, key: &StateKey, op: &WriteOp) -> Fee;

/// Calculates the storage fee for an event.
fn storage_fee_per_event(&self, event: &ContractEvent) -> Fee;
Expand All @@ -116,16 +119,16 @@ pub trait AptosGasMeter: MoveGasMeter {
fn storage_fee_for_transaction_storage(&self, txn_size: NumBytes) -> Fee;

/// Charges the storage fees for writes, events & txn storage in a lump sum, minimizing the
/// loss of precision.
/// loss of precision. Refundable portion of the charge is recorded on the WriteOp itself,
/// due to which mutable references are required on the parameter list wherever proper.
///
/// The contract requires that this function behaves in a way that is consistent to
/// the ones defining the costs.
/// Due to this reason, you should normally not override the default implementation,
/// unless you are doing something special, such as injecting additional logging logic.
fn charge_storage_fee_for_all<'a>(
fn process_storage_fee_for_all(
&mut self,
write_ops: impl IntoIterator<Item = (&'a StateKey, &'a WriteOp)>,
events: impl IntoIterator<Item = &'a ContractEvent>,
change_set: &mut VMChangeSet,
txn_size: NumBytes,
gas_unit_price: FeePerGasUnit,
) -> VMResult<()> {
Expand All @@ -142,10 +145,16 @@ pub trait AptosGasMeter: MoveGasMeter {
}

// Calculate the storage fees.
let write_fee = write_ops.into_iter().fold(Fee::new(0), |acc, (key, op)| {
acc + self.storage_fee_per_write(key, op)
});
let event_fee = events.into_iter().fold(Fee::new(0), |acc, event| {
let write_fee = change_set
.write_set_iter_mut()
.fold(Fee::new(0), |acc, (key, op)| {
let slot_fee = self.storage_fee_for_state_slot(op);
let bytes_fee = self.storage_fee_for_state_bytes(key, op);
Self::maybe_record_storage_deposit(op, slot_fee);

acc + slot_fee + bytes_fee
});
let event_fee = change_set.events().iter().fold(Fee::new(0), |acc, event| {
acc + self.storage_fee_per_event(event)
});
let event_discount = self.storage_discount_for_events(event_fee);
Expand All @@ -161,6 +170,28 @@ pub trait AptosGasMeter: MoveGasMeter {
Ok(())
}

// The slot fee is refundable, we record it on the WriteOp itself and it'll end up in
// the state DB.
fn maybe_record_storage_deposit(write_op: &mut WriteOp, slot_fee: Fee) {
use WriteOp::*;

match write_op {
CreationWithMetadata {
ref mut metadata,
data: _,
} => {
if !slot_fee.is_zero() {
metadata.set_deposit(slot_fee.into())
}
},
Creation(..)
| Modification(..)
| Deletion
| ModificationWithMetadata { .. }
| DeletionWithMetadata { .. } => {},
}
}

// Below are getters reexported from the gas algebra.
// Gas meter instances should not reimplement these themselves.

Expand Down
1 change: 1 addition & 0 deletions aptos-move/aptos-gas-profiling/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ aptos-gas-algebra = { workspace = true }
aptos-gas-meter = { workspace = true }
aptos-package-builder = { workspace = true }
aptos-types = { workspace = true }
aptos-vm-types = { workspace = true }

move-binary-format = { workspace = true }
move-core-types = { workspace = true }
Expand Down
20 changes: 13 additions & 7 deletions aptos-move/aptos-gas-profiling/src/profiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use aptos_gas_meter::AptosGasMeter;
use aptos_types::{
contract_event::ContractEvent, state_store::state_key::StateKey, write_set::WriteOp,
};
use aptos_vm_types::change_set::VMChangeSet;
use move_binary_format::{
errors::{Location, PartialVMResult, VMResult},
file_format::CodeOffset,
Expand Down Expand Up @@ -479,7 +480,9 @@ where
delegate! {
fn algebra(&self) -> &Self::Algebra;

fn storage_fee_per_write(&self, key: &StateKey, op: &WriteOp) -> Fee;
fn storage_fee_for_state_slot(&self, op: &WriteOp) -> Fee;

fn storage_fee_for_state_bytes(&self, key: &StateKey, op: &WriteOp) -> Fee;

fn storage_fee_per_event(&self, event: &ContractEvent) -> Fee;

Expand Down Expand Up @@ -511,10 +514,9 @@ where
res
}

fn charge_storage_fee_for_all<'a>(
fn process_storage_fee_for_all(
&mut self,
write_ops: impl IntoIterator<Item = (&'a StateKey, &'a WriteOp)>,
events: impl IntoIterator<Item = &'a ContractEvent>,
change_set: &mut VMChangeSet,
txn_size: NumBytes,
gas_unit_price: FeePerGasUnit,
) -> VMResult<()> {
Expand All @@ -533,8 +535,12 @@ where
// Writes
let mut write_fee = Fee::new(0);
let mut write_set_storage = vec![];
for (key, op) in write_ops.into_iter() {
let fee = self.storage_fee_per_write(key, op);
for (key, op) in change_set.write_set_iter_mut() {
let slot_fee = self.storage_fee_for_state_slot(op);
let bytes_fee = self.storage_fee_for_state_bytes(key, op);
Self::maybe_record_storage_deposit(op, slot_fee);

let fee = slot_fee + bytes_fee;
write_set_storage.push(WriteStorage {
key: key.clone(),
op_type: write_op_type(op),
Expand All @@ -546,7 +552,7 @@ where
// Events
let mut event_fee = Fee::new(0);
let mut event_fees = vec![];
for event in events {
for event in change_set.events().iter() {
let fee = self.storage_fee_per_event(event);
event_fees.push(EventStorage {
ty: event.type_tag().clone(),
Expand Down
32 changes: 18 additions & 14 deletions aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,27 +189,31 @@ impl TransactionGasParameters {
}
}

/// New formula to charge storage fee for a write, measured in APT.
pub fn storage_fee_per_write(&self, key: &StateKey, op: &WriteOp) -> Fee {
pub fn storage_fee_for_slot(&self, op: &WriteOp) -> Fee {
use WriteOp::*;

let excess_fee = |key: &StateKey, data: &[u8]| -> Fee {
let size = NumBytes::new(key.size() as u64) + NumBytes::new(data.len() as u64);
match size.checked_sub(self.free_write_bytes_quota) {
Some(excess) => excess * self.storage_fee_per_excess_state_byte,
None => 0.into(),
}
};

match op {
Creation(data) | CreationWithMetadata { data, .. } => {
self.storage_fee_per_state_slot_create * NumSlots::new(1) + excess_fee(key, data)
Creation(..) | CreationWithMetadata { .. } => {
self.storage_fee_per_state_slot_create * NumSlots::new(1)
},
Modification(data) | ModificationWithMetadata { data, .. } => excess_fee(key, data),
Deletion | DeletionWithMetadata { .. } => 0.into(),
Modification(..)
| ModificationWithMetadata { .. }
| Deletion
| DeletionWithMetadata { .. } => 0.into(),
}
}

pub fn storage_fee_for_bytes(&self, key: &StateKey, op: &WriteOp) -> Fee {
if let Some(data) = op.bytes() {
let size = NumBytes::new(key.size() as u64) + NumBytes::new(data.len() as u64);
if let Some(excess) = size.checked_sub(self.free_write_bytes_quota) {
return excess * self.storage_fee_per_excess_state_byte;
}
}

0.into()
}

/// New formula to charge storage fee for an event, measured in APT.
pub fn storage_fee_per_event(&self, event: &ContractEvent) -> Fee {
NumBytes::new(event.size() as u64) * self.storage_fee_per_event_byte
Expand Down
4 changes: 3 additions & 1 deletion aptos-move/aptos-memory-usage-tracker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,9 @@ where
delegate! {
fn algebra(&self) -> &Self::Algebra;

fn storage_fee_per_write(&self, key: &StateKey, op: &WriteOp) -> Fee;
fn storage_fee_for_state_slot(&self, op: &WriteOp) -> Fee;

fn storage_fee_for_state_bytes(&self, key: &StateKey, op: &WriteOp) -> Fee;

fn storage_fee_per_event(&self, event: &ContractEvent) -> Fee;

Expand Down
7 changes: 7 additions & 0 deletions aptos-move/aptos-vm-types/src/change_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ impl VMChangeSet {
.chain(self.aggregator_write_set.iter())
}

pub fn write_set_iter_mut(&mut self) -> impl Iterator<Item = (&StateKey, &mut WriteOp)> {
self.resource_write_set
.iter_mut()
.chain(self.module_write_set.iter_mut())
.chain(self.aggregator_write_set.iter_mut())
}

pub fn resource_write_set(&self) -> &BTreeMap<StateKey, WriteOp> {
&self.resource_write_set
}
Expand Down
7 changes: 3 additions & 4 deletions aptos-move/aptos-vm/src/aptos_vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,15 +491,14 @@ impl AptosVM {
change_set_configs: &ChangeSetConfigs,
txn_data: &TransactionMetadata,
) -> Result<RespawnedSession<'r, 'l>, VMStatus> {
let change_set = session.finish(&mut (), change_set_configs)?;
let mut change_set = session.finish(&mut (), change_set_configs)?;

for (key, op) in change_set.write_set_iter() {
gas_meter.charge_io_gas_for_write(key, op)?;
}

gas_meter.charge_storage_fee_for_all(
change_set.write_set_iter(),
change_set.events(),
gas_meter.process_storage_fee_for_all(
&mut change_set,
txn_data.transaction_size,
txn_data.gas_unit_price,
)?;
Expand Down
10 changes: 4 additions & 6 deletions aptos-move/aptos-vm/src/aptos_vm_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use aptos_gas_schedule::{
AptosGasParameters, FromOnChainGasSchedule, MiscGasParameters, NativeGasParameters,
};
use aptos_logger::{enabled, prelude::*, Level};
use aptos_state_view::StateView;
use aptos_state_view::{StateView, StateViewId};
use aptos_types::{
account_config::CORE_CODE_ADDRESS,
chain_id::ChainId,
Expand Down Expand Up @@ -642,11 +642,9 @@ impl<'a> AptosVMInternals<'a> {
}

/// Returns the internal gas schedule if it has been loaded, or an error if it hasn't.
pub fn gas_params(
self,
log_context: &AdapterLogSchema,
) -> Result<&'a AptosGasParameters, VMStatus> {
self.0.get_gas_parameters(log_context)
pub fn gas_params(self) -> Result<&'a AptosGasParameters, VMStatus> {
let log_context = AdapterLogSchema::new(StateViewId::Miscellaneous, 0);
self.0.get_gas_parameters(&log_context)
}

/// Returns the version of Move Runtime.
Expand Down
22 changes: 4 additions & 18 deletions aptos-move/aptos-vm/src/move_vm_ext/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,35 +123,23 @@ impl SessionId {
pub fn as_uuid(&self) -> HashValue {
self.hash()
}

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

pub struct SessionExt<'r, 'l> {
inner: Session<'r, 'l>,
remote: &'r dyn MoveResolverExt,
new_slot_payer: Option<AccountAddress>,
features: Arc<Features>,
}

impl<'r, 'l> SessionExt<'r, 'l> {
pub fn new(
inner: Session<'r, 'l>,
remote: &'r dyn MoveResolverExt,
new_slot_payer: Option<AccountAddress>,
features: Arc<Features>,
) -> Self {
Self {
inner,
remote,
new_slot_payer,
features,
}
}
Expand All @@ -178,7 +166,6 @@ impl<'r, 'l> SessionExt<'r, 'l> {

let change_set = Self::convert_change_set(
self.remote,
self.new_slot_payer,
self.features.is_storage_slot_metadata_enabled(),
current_time.as_ref(),
change_set,
Expand Down Expand Up @@ -306,7 +293,6 @@ impl<'r, 'l> SessionExt<'r, 'l> {

pub fn convert_change_set<C: AccessPathCache>(
remote: &dyn MoveResolverExt,
new_slot_payer: Option<AccountAddress>,
is_storage_slot_metadata_enabled: bool,
current_time: Option<&CurrentTimeMicroseconds>,
change_set: MoveChangeSet,
Expand All @@ -319,10 +305,10 @@ impl<'r, 'l> SessionExt<'r, 'l> {
) -> Result<VMChangeSet, VMStatus> {
let mut new_slot_metadata: Option<StateValueMetadata> = None;
if is_storage_slot_metadata_enabled {
if let Some(payer) = new_slot_payer {
if let Some(current_time) = current_time {
new_slot_metadata = Some(StateValueMetadata::new(payer, 0, current_time));
}
if let Some(current_time) = current_time {
// The deposit on the metadata is a placeholder (0), it will be updated later when
// storage fee is charged.
new_slot_metadata = Some(StateValueMetadata::new(0, current_time));
}
}
let woc = WriteOpConverter {
Expand Down
2 changes: 0 additions & 2 deletions aptos-move/aptos-vm/src/move_vm_ext/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ impl MoveVmExt {
extensions.add(AlgebraContext::new());
extensions.add(NativeAggregatorContext::new(txn_hash, remote));

let sender_opt = session_id.sender();
let script_hash = match session_id {
SessionId::Txn {
sender: _,
Expand Down Expand Up @@ -196,7 +195,6 @@ impl MoveVmExt {
SessionExt::new(
self.inner.new_session_with_extensions(remote, extensions),
remote,
sender_opt,
self.features.clone(),
)
}
Expand Down
5 changes: 5 additions & 0 deletions aptos-move/e2e-move-tests/src/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use aptos_types::{
TransactionPayload, TransactionStatus,
},
};
use aptos_vm::AptosVM;
use move_core_types::{
language_storage::{StructTag, TypeTag},
move_resource::MoveStructType,
Expand Down Expand Up @@ -603,6 +604,10 @@ impl MoveHarness {
);
}

pub fn new_vm(&self) -> AptosVM {
AptosVM::new(self.executor.data_store())
}

pub fn set_default_gas_unit_price(&mut self, gas_unit_price: u64) {
self.default_gas_unit_price = gas_unit_price;
}
Expand Down
Loading
Loading