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

Storage fee for state bytes refundable #11279

Merged
merged 5 commits into from
Feb 14, 2024
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
2 changes: 2 additions & 0 deletions Cargo.lock

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

8 changes: 8 additions & 0 deletions aptos-move/aptos-aggregator/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ pub trait TAggregatorV1View {
Ok(maybe_state_value.map(StateValue::into_metadata))
}

fn get_aggregator_v1_state_value_size(
&self,
id: &Self::Identifier,
) -> PartialVMResult<Option<u64>> {
let maybe_state_value = self.get_aggregator_v1_state_value(id)?;
Ok(maybe_state_value.map(|v| v.size() as u64))
}

/// Consumes a single delta of aggregator V1, and tries to materialize it
/// with a given identifier (state key). If materialization succeeds, a
/// write op is produced.
Expand Down
28 changes: 17 additions & 11 deletions aptos-move/aptos-gas-meter/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use aptos_gas_schedule::VMGasParameters;
use aptos_types::{state_store::state_key::StateKey, write_set::WriteOpSize};
use aptos_vm_types::{
change_set::VMChangeSet,
resolver::ExecutorView,
storage::{
io_pricing::IoPricing,
space_pricing::{ChargeAndRefund, DiskSpacePricing},
Expand Down Expand Up @@ -126,6 +127,7 @@ pub trait AptosGasMeter: MoveGasMeter {
change_set: &mut VMChangeSet,
txn_size: NumBytes,
gas_unit_price: FeePerGasUnit,
executor_view: &dyn ExecutorView,
) -> VMResult<Fee> {
// The new storage fee are only active since version 7.
if self.feature_version() < 7 {
Expand All @@ -142,30 +144,34 @@ pub trait AptosGasMeter: MoveGasMeter {
let pricing = self.disk_space_pricing();
let params = &self.vm_gas_params().txn;

// Calculate the storage fees.
// Write set
let mut write_fee = Fee::new(0);
let mut total_refund = Fee::new(0);
for (key, op_size, metadata_opt) in change_set.write_set_iter_mut() {
let ChargeAndRefund { charge, refund } =
pricing.charge_refund_write_op(params, key, &op_size, metadata_opt);
total_refund += refund;

for res in change_set.write_op_info_iter_mut(executor_view) {
let ChargeAndRefund { charge, refund } = pricing.charge_refund_write_op(
params,
res.map_err(|err| err.finish(Location::Undefined))?,
);
write_fee += charge;
total_refund += refund;
}

// Events (no event fee in v2)
let event_fee = change_set
.events()
.iter()
.fold(Fee::new(0), |acc, (event, _)| {
acc + pricing.storage_fee_per_event(params, event)
acc + pricing.legacy_storage_fee_per_event(params, event)
});
let event_discount = pricing.storage_discount_for_events(params, event_fee);
let event_discount = pricing.legacy_storage_discount_for_events(params, event_fee);
let event_net_fee = event_fee
.checked_sub(event_discount)
.expect("discount should always be less than or equal to total amount");
let txn_fee = pricing.storage_fee_for_transaction_storage(params, txn_size);
let fee = write_fee + event_net_fee + txn_fee;
.expect("event discount should always be less than or equal to total amount");

// Txn (no txn fee in v2)
let txn_fee = pricing.legacy_storage_fee_for_transaction_storage(params, txn_size);

let fee = write_fee + event_net_fee + txn_fee;
self.charge_storage_fee(fee, gas_unit_price)
.map_err(|err| err.finish(Location::Undefined))?;

Expand Down
38 changes: 21 additions & 17 deletions aptos-move/aptos-gas-profiling/src/profiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use crate::log::{
use aptos_gas_algebra::{Fee, FeePerGasUnit, InternalGas, NumArgs, NumBytes};
use aptos_gas_meter::AptosGasMeter;
use aptos_types::{state_store::state_key::StateKey, write_set::WriteOpSize};
use aptos_vm_types::{change_set::VMChangeSet, storage::space_pricing::ChargeAndRefund};
use aptos_vm_types::{
change_set::VMChangeSet, resolver::ExecutorView, storage::space_pricing::ChargeAndRefund,
};
use move_binary_format::{
errors::{Location, PartialVMResult, VMResult},
file_format::CodeOffset,
Expand Down Expand Up @@ -507,6 +509,7 @@ where
change_set: &mut VMChangeSet,
txn_size: NumBytes,
gas_unit_price: FeePerGasUnit,
executor_view: &dyn ExecutorView,
) -> VMResult<Fee> {
// The new storage fee are only active since version 7.
if self.feature_version() < 7 {
Expand All @@ -523,42 +526,45 @@ where
let pricing = self.disk_space_pricing();
let params = &self.vm_gas_params().txn;

// Writes
// Write set
let mut write_fee = Fee::new(0);
let mut write_set_storage = vec![];
let mut total_refund = Fee::new(0);
for (key, op_size, metadata_opt) in change_set.write_set_iter_mut() {
for res in change_set.write_op_info_iter_mut(executor_view) {
let write_op_info = res.map_err(|err| err.finish(Location::Undefined))?;
let key = write_op_info.key.clone();
let op_type = write_op_type(&write_op_info.op_size);
let ChargeAndRefund { charge, refund } =
pricing.charge_refund_write_op(params, key, &op_size, metadata_opt);
pricing.charge_refund_write_op(params, write_op_info);
write_fee += charge;
total_refund += refund;

write_set_storage.push(WriteStorage {
key: key.clone(),
op_type: write_op_type(&op_size),
key,
op_type,
cost: charge,
refund,
});
}

// Events
// Events (no event fee in v2)
let mut event_fee = Fee::new(0);
let mut event_fees = vec![];
for (event, _) in change_set.events().iter() {
let fee = pricing.storage_fee_per_event(params, event);
let fee = pricing.legacy_storage_fee_per_event(params, event);
event_fees.push(EventStorage {
ty: event.type_tag().clone(),
cost: fee,
});
event_fee += fee;
}
let event_discount = pricing.storage_discount_for_events(params, event_fee);
let event_fee_with_discount = event_fee
let event_discount = pricing.legacy_storage_discount_for_events(params, event_fee);
let event_net_fee = event_fee
.checked_sub(event_discount)
.expect("discount should always be less than or equal to total amount");

// Txn
let txn_fee = pricing.storage_fee_for_transaction_storage(params, txn_size);
// Txn (no txn fee in v2)
let txn_fee = pricing.legacy_storage_fee_for_transaction_storage(params, txn_size);

self.storage_fees = Some(StorageFees {
total: write_fee + event_fee + txn_fee,
Expand All @@ -570,11 +576,9 @@ where
txn_storage: txn_fee,
});

self.charge_storage_fee(
write_fee + event_fee_with_discount + txn_fee,
gas_unit_price,
)
.map_err(|err| err.finish(Location::Undefined))?;
let fee = write_fee + event_net_fee + txn_fee;
self.charge_storage_fee(fee, gas_unit_price)
.map_err(|err| err.finish(Location::Undefined))?;

Ok(total_refund)
}
Expand Down
1 change: 1 addition & 0 deletions aptos-move/aptos-gas-schedule/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ either = { workspace = true }
move-core-types = { workspace = true }
move-vm-types = { workspace = true }
paste = { workspace = true }
rand = { workspace = true }

[features]
testing = ["aptos-global-constants/testing"]
7 changes: 7 additions & 0 deletions aptos-move/aptos-gas-schedule/src/gas_schedule/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ macro_rules! define_gas_parameters {
$($name: 0.into()),*
}
}

#[cfg(feature = "testing")]
pub fn random() -> Self {
Self {
$($name: rand::random::<u64>().into()),*
}
}
}

impl $crate::traits::InitialGasSchedule for $params_name {
Expand Down
32 changes: 22 additions & 10 deletions aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ crate::gas_schedule::macros::define_gas_parameters!(
1024, // 1KB free per state write
],
[
free_event_bytes_quota: NumBytes,
{ 7.. => "free_event_bytes_quota" },
legacy_free_event_bytes_quota: NumBytes,
{ 7..=12 => "free_event_bytes_quota", 13.. => "legacy_free_event_bytes_quota" },
1024, // 1KB free event bytes per transaction
],
[
Expand Down Expand Up @@ -154,23 +154,35 @@ crate::gas_schedule::macros::define_gas_parameters!(
8192,
],
[
storage_fee_per_state_slot_create: FeePerSlot,
{ 7.. => "storage_fee_per_state_slot_create" },
legacy_storage_fee_per_state_slot_create: FeePerSlot,
{ 7..=12 => "storage_fee_per_state_slot_create", 13 => "legacy_storage_fee_per_state_slot_create" },
50000,
],
[
storage_fee_per_excess_state_byte: FeePerByte,
{ 7.. => "storage_fee_per_excess_state_byte" },
storage_fee_per_state_slot: FeePerSlot,
{ 13.. => "storage_fee_per_state_slot" },
// 0.8 million APT for 2 billion state slots
40_000,
],
[
legacy_storage_fee_per_excess_state_byte: FeePerByte,
{ 7..=12 => "storage_fee_per_excess_state_byte", 13 => "legacy_storage_fee_per_excess_state_byte" },
50,
],
[
storage_fee_per_event_byte: FeePerByte,
{ 7.. => "storage_fee_per_event_byte" },
storage_fee_per_state_byte: FeePerByte,
{ 13.. => "storage_fee_per_state_byte" },
// 0.8 million APT for 2 TB state bytes
40,
],
[
legacy_storage_fee_per_event_byte: FeePerByte,
{ 7..=12 => "storage_fee_per_event_byte", 13 => "legacy_storage_fee_per_event_byte" },
20,
],
[
storage_fee_per_transaction_byte: FeePerByte,
{ 7.. => "storage_fee_per_transaction_byte" },
legacy_storage_fee_per_transaction_byte: FeePerByte,
{ 7..=12 => "storage_fee_per_transaction_byte", 13 => "legacy_storage_fee_per_transaction_byte" },
20,
],
[
Expand Down
5 changes: 4 additions & 1 deletion aptos-move/aptos-gas-schedule/src/ver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
/// - Changing how gas is calculated in any way
///
/// Change log:
/// - V13
/// - Storage Fee: Make state bytes refundable and remove the per slot free quota, gated by flag REFUNDABLE_BYTES
/// - V12
/// - Added BN254 operations.
/// - IO gas change: 1. read bytes charged at 4KB intervals; 2. ignore free_write_bytes_quota
/// - V11
/// - Ristretto255 natives (point cloning & double-scalar multiplication) and Bulletproofs natives
/// - Hard limit on the number of write ops per transaction
Expand Down Expand Up @@ -44,4 +47,4 @@
/// global operations.
/// - V1
/// - TBA
pub const LATEST_GAS_FEATURE_VERSION: u64 = 12;
pub const LATEST_GAS_FEATURE_VERSION: u64 = 13;
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ pub enum FeatureFlag {
RemoveDetailedError,
JWKConsensus,
ConcurrentFungibleAssets,
RefundableBytes,
}

fn generate_features_blob(writer: &CodeWriter, data: &[u64]) {
Expand Down Expand Up @@ -260,6 +261,7 @@ impl From<FeatureFlag> for AptosFeatureFlag {
FeatureFlag::RemoveDetailedError => AptosFeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH,
FeatureFlag::JWKConsensus => AptosFeatureFlag::JWK_CONSENSUS,
FeatureFlag::ConcurrentFungibleAssets => AptosFeatureFlag::CONCURRENT_FUNGIBLE_ASSETS,
FeatureFlag::RefundableBytes => AptosFeatureFlag::REFUNDABLE_BYTES,
}
}
}
Expand Down Expand Up @@ -342,6 +344,7 @@ impl From<AptosFeatureFlag> for FeatureFlag {
AptosFeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH => FeatureFlag::RemoveDetailedError,
AptosFeatureFlag::JWK_CONSENSUS => FeatureFlag::JWKConsensus,
AptosFeatureFlag::CONCURRENT_FUNGIBLE_ASSETS => FeatureFlag::ConcurrentFungibleAssets,
AptosFeatureFlag::REFUNDABLE_BYTES => FeatureFlag::RefundableBytes,
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ task 2 'run'. lines 32-32:
Events:
{
type: 0x1::transaction_fee::FeeStatement
data: "36000000000000000300000000000000010000000000000050c30000000000000000000000000000"
data: "30000000000000000300000000000000010000000000000030ac0000000000000000000000000000"
}mutable inputs after call: local#0: 0
return values: 0

task 3 'run'. lines 34-34:
Events:
{
type: 0x1::transaction_fee::FeeStatement
data: "04000000000000000300000000000000020000000000000000000000000000000000000000000000"
data: "05000000000000000300000000000000020000000000000018010000000000000000000000000000"
}mutable inputs after call: local#0: 0
return values: 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Events:
}
{
type: 0x1::transaction_fee::FeeStatement
data: "6a0000000000000004000000000000000200000000000000a0860100000000000000000000000000"
data: "64000000000000000400000000000000020000000000000028720100000000000000000000000000"
}mutable inputs after call: local#0: 0
return values: 0

Expand All @@ -36,7 +36,7 @@ Events:
}
{
type: 0x1::transaction_fee::FeeStatement
data: "9f0000000000000006000000000000000300000000000000f0490200000000000000000000000000"
data: "9b0000000000000006000000000000000300000000000000c83a0200000000000000000000000000"
}mutable inputs after call: local#0: 0
return values: 0

Expand Down Expand Up @@ -96,7 +96,7 @@ Events:
}
{
type: 0x1::transaction_fee::FeeStatement
data: "6c0000000000000005000000000000000300000000000000a0860100000000000000000000000000"
data: "6b000000000000000500000000000000030000000000000018820100000000000000000000000000"
}mutable inputs after call: local#0: 0
return values: 0

Expand All @@ -116,7 +116,7 @@ Events:
}
{
type: 0x1::transaction_fee::FeeStatement
data: "6c0000000000000005000000000000000300000000000000a08601000000000050c3000000000000"
data: "6b0000000000000005000000000000000300000000000000b88201000000000058bb000000000000"
}mutable inputs after call: local#0: 0
return values: 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ task 2 'run'. lines 36-36:
Events:
{
type: 0x1::transaction_fee::FeeStatement
data: "36000000000000000300000000000000010000000000000050c30000000000000000000000000000"
data: "30000000000000000300000000000000010000000000000030ac0000000000000000000000000000"
}mutable inputs after call: local#0: 0
return values: 0

task 3 'run'. lines 38-38:
Events:
{
type: 0x1::transaction_fee::FeeStatement
data: "04000000000000000300000000000000020000000000000000000000000000000000000000000000"
data: "05000000000000000300000000000000020000000000000018010000000000000000000000000000"
}mutable inputs after call: local#0: 0
return values: 0

Expand Down
1 change: 1 addition & 0 deletions aptos-move/aptos-vm-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ serde = { workspace = true }

[dev-dependencies]
aptos-aggregator = { workspace = true, features = ["testing"] }
aptos-gas-schedule = { workspace = true, features = ["testing"] }
aptos-language-e2e-tests = { workspace = true }
aptos-vm = { workspace = true }
test-case = { workspace = true }
Loading
Loading