Skip to content

Commit

Permalink
Natives cost 2/x: Update protocol configs with natives costs (MystenL…
Browse files Browse the repository at this point in the history
…abs#8834)

## Description 

This exposes native cost factors for `event` and `address` in protocol
configs.

## Test Plan 

N/A

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
  • Loading branch information
oxade authored Mar 3, 2023
1 parent 58de5ab commit bbdd685
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 52 deletions.
6 changes: 5 additions & 1 deletion crates/sui-adapter/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ use move_vm_runtime::{
};

use sui_cost_tables::bytecode_tables::GasStatus;
use sui_framework::natives::object_runtime::{self, ObjectRuntime};
use sui_framework::natives::{
object_runtime::{self, ObjectRuntime},
NativesCostTable,
};
use sui_json::primitive_type;
use sui_protocol_config::ProtocolConfig;
use sui_types::{
Expand Down Expand Up @@ -105,6 +108,7 @@ pub fn new_session<
is_metered,
protocol_config,
));
extensions.add(NativesCostTable::from_protocol_config(protocol_config));
vm.new_session_with_extensions(state_view, extensions)
}

Expand Down
14 changes: 0 additions & 14 deletions crates/sui-cost-tables/src/natives_tables.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use move_core_types::gas_algebra::{GasQuantity, InternalGas, InternalGasUnit};

//
// Native function costs
//
Expand All @@ -25,15 +23,3 @@ pub enum SuiNativeCostIndex {
TX_CONTEXT_DERIVE_ID = 7,
TX_CONTEXT_NEW_SIGNER_FROM_ADDR = 8,
}

pub const NATIVES_COST_LOW: GasQuantity<InternalGasUnit> = InternalGas::new(10);
pub const NATIVES_COST_MID: GasQuantity<InternalGasUnit> = InternalGas::new(1_000);
pub const NATIVES_COST_HIGH: GasQuantity<InternalGasUnit> = InternalGas::new(1_000_000);

/// Base fee for entering a native fn
pub const NATIVES_COST_BASE_ENTRY: GasQuantity<InternalGasUnit> = NATIVES_COST_HIGH;

#[test]
pub fn test_natives_cost_tiers() {
assert!((NATIVES_COST_LOW < NATIVES_COST_MID) && (NATIVES_COST_MID < NATIVES_COST_HIGH));
}
68 changes: 51 additions & 17 deletions crates/sui-framework/src/natives/address.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use crate::natives::NativesCostTable;
use move_binary_format::errors::PartialVMResult;
use move_core_types::{account_address::AccountAddress, u256::U256};
use move_core_types::{account_address::AccountAddress, gas_algebra::InternalGas, u256::U256};
use move_vm_runtime::{
native_charge_gas_early_exit, native_functions::NativeContext, native_gas_total_cost,
};
Expand All @@ -11,14 +12,16 @@ use move_vm_types::{
};
use smallvec::smallvec;
use std::{collections::VecDeque, ops::Mul};
use sui_cost_tables::natives_tables::NATIVES_COST_LOW;

const E_ADDRESS_PARSE_ERROR: u64 = 0;

pub struct AddressFromBytesCostParams {
pub copy_bytes_to_address_cost_per_byte: InternalGas,
}
/***************************************************************************************************
* native fun from_bytes
* Implementation of the Move native function `address::from_bytes(bytes: vector<u8>)`
* gas cost: NATIVES_COST_LOW * AccountAddress::LENGTH | converting bytes into an address
* gas cost: copy_bytes_to_address_cost_per_byte * AccountAddress::LENGTH | converting bytes into an address
*
**************************************************************************************************/
pub fn from_bytes(
Expand All @@ -29,12 +32,17 @@ pub fn from_bytes(
debug_assert!(ty_args.is_empty());
debug_assert!(args.len() == 1);
let mut gas_left = context.gas_budget();
let natvies_cost_table: &NativesCostTable = context.extensions_mut().get();
let address_from_bytes_cost_params = &natvies_cost_table.address_from_bytes_cost_params;

let addr_bytes = pop_arg!(args, Vec<u8>);
// Copying bytes is a simple low-cost operation
native_charge_gas_early_exit!(
context,
gas_left,
NATIVES_COST_LOW.mul((AccountAddress::LENGTH as u64).into())
address_from_bytes_cost_params
.copy_bytes_to_address_cost_per_byte
.mul((AccountAddress::LENGTH as u64).into())
);

let cost = native_gas_total_cost!(context, gas_left);
Expand All @@ -46,12 +54,17 @@ pub fn from_bytes(
})
}

pub struct AddressToU256CostParams {
pub address_to_vec_cost_per_byte: InternalGas,
pub address_vec_reverse_cost_per_byte: InternalGas,
pub copy_convert_to_u256_cost_per_byte: InternalGas,
}
/***************************************************************************************************
* native fun to_u256
* Implementation of the Move native function `address::to_u256(address): u256`
* gas cost: NATIVES_COST_LOW * AccountAddress::LENGTH | converting address into an vec<u8>
* + NATIVES_COST_LOW * AccountAddress::LENGTH | reversing the vec<u8>
* + NATIVES_COST_LOW * 2 * AccountAddress::LENGTH | copying and converting to Value::u256
* gas cost: address_to_vec_cost_per_byte * AccountAddress::LENGTH | converting address into an vec<u8>
* + address_vec_reverse_cost_per_byte * AccountAddress::LENGTH | reversing the vec<u8>
* + copy_convert_to_u256_cost_per_byte * 2 * AccountAddress::LENGTH | copying and converting to Value::u256
**************************************************************************************************/
pub fn to_u256(
context: &mut NativeContext,
Expand All @@ -61,28 +74,36 @@ pub fn to_u256(
debug_assert!(ty_args.is_empty());
debug_assert!(args.len() == 1);
let mut gas_left = context.gas_budget();
let natvies_cost_table: &NativesCostTable = context.extensions_mut().get();
let address_to_u256_cost_params = &natvies_cost_table.address_to_u256_cost_params;

let addr = pop_arg!(args, AccountAddress);
// Copying bytes is a simple low-cost operation
native_charge_gas_early_exit!(
context,
gas_left,
NATIVES_COST_LOW.mul((AccountAddress::LENGTH as u64).into())
address_to_u256_cost_params
.address_to_vec_cost_per_byte
.mul((AccountAddress::LENGTH as u64).into())
);
let mut addr_bytes_le = addr.to_vec();
// Reversing bytes is a simple low-cost operation
native_charge_gas_early_exit!(
context,
gas_left,
NATIVES_COST_LOW.mul((AccountAddress::LENGTH as u64).into())
address_to_u256_cost_params
.address_vec_reverse_cost_per_byte
.mul((AccountAddress::LENGTH as u64).into())
);
addr_bytes_le.reverse();

// Copying bytes and converting to Value::u256 are simple low-cost operation
native_charge_gas_early_exit!(
context,
gas_left,
NATIVES_COST_LOW.mul((2 * AccountAddress::LENGTH as u64).into())
address_to_u256_cost_params
.copy_convert_to_u256_cost_per_byte
.mul((2 * AccountAddress::LENGTH as u64).into())
);
// unwrap safe because we know addr_bytes_le is length 32
let u256_val = Value::u256(U256::from_le_bytes(&addr_bytes_le.try_into().unwrap()));
Expand All @@ -92,12 +113,17 @@ pub fn to_u256(
))
}

pub struct AddressFromU256CostParams {
pub u256_to_bytes_to_vec_cost_per_byte: InternalGas,
pub u256_bytes_vec_reverse_cost_per_byte: InternalGas,
pub copy_convert_to_address_cost_per_byte: InternalGas,
}
/***************************************************************************************************
* native fun from_u256
* Implementation of the Move native function `address::from_u256(u256): address`
* gas cost: NATIVES_COST_LOW * 2 * AccountAddress::LENGTH | converting u256 into byte[] and vec<u8>
* + NATIVES_COST_LOW * AccountAddress::LENGTH | reversing the vec<u8>
* + NATIVES_COST_LOW * 2 * AccountAddress::LENGTH | copying and converting to Address::address
* gas cost: u256_to_bytes_to_vec_cost_per_byte * 2 * AccountAddress::LENGTH | converting u256 into byte[] and vec<u8>
* + u256_bytes_vec_reverse_cost_per_byte * AccountAddress::LENGTH | reversing the vec<u8>
* + copy_convert_to_address_cost_per_byte * 2 * AccountAddress::LENGTH | copying and converting to Address::address
**************************************************************************************************/
pub fn from_u256(
context: &mut NativeContext,
Expand All @@ -107,29 +133,37 @@ pub fn from_u256(
debug_assert!(ty_args.is_empty());
debug_assert!(args.len() == 1);
let mut gas_left = context.gas_budget();
let natvies_cost_table: &NativesCostTable = context.extensions_mut().get();
let address_from_u256_cost_params = &natvies_cost_table.address_from_u256_cost_params;

let u256 = pop_arg!(args, U256);

// Copying bytes snd converting sre simple low-cost operations
native_charge_gas_early_exit!(
context,
gas_left,
NATIVES_COST_LOW.mul((2 * AccountAddress::LENGTH as u64).into())
address_from_u256_cost_params
.u256_to_bytes_to_vec_cost_per_byte
.mul((2 * AccountAddress::LENGTH as u64).into())
);
let mut u256_bytes = u256.to_le_bytes().to_vec();
// Reversing bytes is a simple low-cost operation
native_charge_gas_early_exit!(
context,
gas_left,
NATIVES_COST_LOW.mul((AccountAddress::LENGTH as u64).into())
address_from_u256_cost_params
.u256_bytes_vec_reverse_cost_per_byte
.mul((AccountAddress::LENGTH as u64).into())
);
u256_bytes.reverse();

// Copying bytes snd converting sre simple low-cost operations
// Copying bytes and converting sre simple low-cost operations
native_charge_gas_early_exit!(
context,
gas_left,
NATIVES_COST_LOW.mul((2 * AccountAddress::LENGTH as u64).into())
address_from_u256_cost_params
.copy_convert_to_address_cost_per_byte
.mul((2 * AccountAddress::LENGTH as u64).into())
);
// unwrap safe because we are passing a 32 byte slice
let addr_val = Value::address(AccountAddress::from_bytes(&u256_bytes[..]).unwrap());
Expand Down
49 changes: 34 additions & 15 deletions crates/sui-framework/src/natives/event.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use crate::natives::object_runtime::ObjectRuntime;
use crate::natives::{object_runtime::ObjectRuntime, NativesCostTable};
use move_binary_format::errors::{PartialVMError, PartialVMResult};
use move_core_types::{language_storage::TypeTag, vm_status::StatusCode};
use move_core_types::{gas_algebra::InternalGas, language_storage::TypeTag, vm_status::StatusCode};
use move_vm_runtime::{
native_charge_gas_early_exit, native_functions::NativeContext, native_gas_total_cost,
};
Expand All @@ -12,16 +12,21 @@ use move_vm_types::{
};
use smallvec::smallvec;
use std::{collections::VecDeque, ops::Mul};
use sui_cost_tables::natives_tables::NATIVES_COST_MID;
use sui_types::error::VMMemoryLimitExceededSubStatusCode;

#[derive(Clone, Debug)]
pub struct EventEmitCostParams {
pub event_value_size_derivation_cost_per_byte: InternalGas,
pub event_tag_size_derivation_cost_per_byte: InternalGas,
pub event_emit_cost_per_byte: InternalGas,
}
/***************************************************************************************************
* native fun to_u256
* native fun emit
* Implementation of the Move native function `event::emit<T: copy + drop>(event: T)`
* Adds an event to the transaction's event log
* gas cost: NATIVES_COST_MID * event_size | derivation of size
* + NATIVES_COST_MID * tag_size | converting type
* + NATIVES_COST_MID * (tag_size + event_size) | emitting the actual event
* gas cost: event_value_size_derivation_cost_per_byte * event_size | derivation of size
* + event_tag_size_derivation_cost_per_byte * tag_size | converting type
* + event_emit_cost_per_byte * (tag_size + event_size) | emitting the actual event
**************************************************************************************************/
pub fn emit(
context: &mut NativeContext,
Expand All @@ -31,17 +36,23 @@ pub fn emit(
debug_assert!(ty_args.len() == 1);
debug_assert!(args.len() == 1);
let mut gas_left = context.gas_budget();
let event_emit_cost_params = {
let natvies_cost_table: &NativesCostTable = context.extensions().get();
natvies_cost_table.event_emit_cost_params.clone()
};

let ty = ty_args.pop().unwrap();
let event = args.pop_back().unwrap();
let event_value = args.pop_back().unwrap();

let event_size = event.legacy_size();
let event_value_size = event_value.legacy_size();

// Deriving event size can be expensive due to recursion overhead
// Deriving event value size can be expensive due to recursion overhead
native_charge_gas_early_exit!(
context,
gas_left,
NATIVES_COST_MID.mul(u64::from(event_size).into())
event_emit_cost_params
.event_value_size_derivation_cost_per_byte
.mul(u64::from(event_value_size).into())
);

let tag = match context.type_to_type_tag(&ty)? {
Expand All @@ -59,12 +70,14 @@ pub fn emit(
native_charge_gas_early_exit!(
context,
gas_left,
NATIVES_COST_MID.mul(u64::from(tag_size).into())
event_emit_cost_params
.event_tag_size_derivation_cost_per_byte
.mul(u64::from(tag_size).into())
);

let obj_runtime: &mut ObjectRuntime = context.extensions_mut().get_mut();
let max_event_emit_size = obj_runtime.constants.max_event_emit_size;
let ev_size = u64::from(tag_size + event_size);
let ev_size = u64::from(tag_size + event_value_size);
if ev_size > max_event_emit_size {
return Err(PartialVMError::new(StatusCode::MEMORY_LIMIT_EXCEEDED)
.with_message(format!(
Expand All @@ -77,8 +90,14 @@ pub fn emit(
let obj_runtime: &mut ObjectRuntime = context.extensions_mut().get_mut();

// Emitting an event is cheap since its a vector push
native_charge_gas_early_exit!(context, gas_left, NATIVES_COST_MID.mul(ev_size.into()));
obj_runtime.emit_event(*tag, event)?;
native_charge_gas_early_exit!(
context,
gas_left,
event_emit_cost_params
.event_emit_cost_per_byte
.mul(ev_size.into())
);
obj_runtime.emit_event(*tag, event_value)?;
Ok(NativeResult::ok(
native_gas_total_cost!(context, gas_left),
smallvec![],
Expand Down
57 changes: 56 additions & 1 deletion crates/sui-framework/src/natives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod types;
mod validator;

use crate::make_native;
use better_any::{Tid, TidAble};
use move_binary_format::errors::{PartialVMError, PartialVMResult};
use move_core_types::{account_address::AccountAddress, identifier::Identifier};
use move_stdlib::natives::{GasParameters, NurseryGasParameters};
Expand All @@ -24,8 +25,62 @@ use move_vm_types::{
values::{Struct, Value},
};
use std::sync::Arc;
use sui_protocol_config::ProtocolConfig;

use self::crypto::{bls12381, ecdsa_k1, ecdsa_r1, ecvrf, ed25519, groth16, hash, hmac, tbls};
use self::{
address::{AddressFromBytesCostParams, AddressFromU256CostParams, AddressToU256CostParams},
crypto::{bls12381, ecdsa_k1, ecdsa_r1, ecvrf, ed25519, groth16, hash, hmac, tbls},
event::EventEmitCostParams,
};

#[derive(Tid)]
pub struct NativesCostTable {
pub address_from_bytes_cost_params: AddressFromBytesCostParams,
pub address_to_u256_cost_params: AddressToU256CostParams,
pub address_from_u256_cost_params: AddressFromU256CostParams,
pub event_emit_cost_params: EventEmitCostParams,
}

impl NativesCostTable {
pub fn from_protocol_config(protocol_config: &ProtocolConfig) -> NativesCostTable {
Self {
address_from_bytes_cost_params: AddressFromBytesCostParams {
copy_bytes_to_address_cost_per_byte: protocol_config
.copy_bytes_to_address_cost_per_byte()
.into(),
},
address_to_u256_cost_params: AddressToU256CostParams {
address_to_vec_cost_per_byte: protocol_config.address_to_vec_cost_per_byte().into(),
address_vec_reverse_cost_per_byte: protocol_config
.address_vec_reverse_cost_per_byte()
.into(),
copy_convert_to_u256_cost_per_byte: protocol_config
.copy_convert_to_u256_cost_per_byte()
.into(),
},
address_from_u256_cost_params: AddressFromU256CostParams {
u256_to_bytes_to_vec_cost_per_byte: protocol_config
.u256_to_bytes_to_vec_cost_per_byte()
.into(),
u256_bytes_vec_reverse_cost_per_byte: protocol_config
.u256_bytes_vec_reverse_cost_per_byte()
.into(),
copy_convert_to_address_cost_per_byte: protocol_config
.u256_bytes_vec_reverse_cost_per_byte()
.into(),
},
event_emit_cost_params: EventEmitCostParams {
event_value_size_derivation_cost_per_byte: protocol_config
.event_value_size_derivation_cost_per_byte()
.into(),
event_tag_size_derivation_cost_per_byte: protocol_config
.event_tag_size_derivation_cost_per_byte()
.into(),
event_emit_cost_per_byte: protocol_config.event_emit_cost_per_byte().into(),
},
}
}
}

pub fn all_natives(
move_stdlib_addr: AccountAddress,
Expand Down
Loading

0 comments on commit bbdd685

Please sign in to comment.