Skip to content

Commit

Permalink
[gas] eliminate consensus gas cost
Browse files Browse the repository at this point in the history
Now that we sequence all transactions (async for single-owner txes, sync for shared object txes), it doesn't make sense to charge a premium for going through consensus. Simplify the gas cost calculation by getting rid of this.

Using hot shared objects will eventually lead to higher fees, but that will happen at a different level (higher tip required for prioritization rather than higher cost).
  • Loading branch information
sblackshear committed Dec 20, 2022
1 parent 731eeb6 commit ae3f487
Show file tree
Hide file tree
Showing 10 changed files with 34 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module test::m {

//# run test::m::abort_

//# run test::m::loop_ --gas-budget 100
//# run test::m::loop_ --gas-budget 1000

//# run test::m::math

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ created: object(110)
written: object(109)

task 7 'run'. lines 82-82:
events: CoinBalanceChange { package_id: sui, transaction_module: Identifier("gas"), sender: B, change_type: Gas, owner: AddressOwner(B), coin_type: "sui::sui::SUI", coin_object_id: fake(111), version: SequenceNumber(1), amount: -82 }, MutateObject { package_id: test, transaction_module: Identifier("object_basics"), sender: B, object_type: "test::object_basics::Object", object_id: fake(107), version: SequenceNumber(4) }, MutateObject { package_id: sui, transaction_module: Identifier("unused_input_object"), sender: B, object_type: "test::object_basics::Object", object_id: fake(110), version: SequenceNumber(4) }, MoveEvent { package_id: test, transaction_module: Identifier("object_basics"), sender: B, type_: StructTag { address: test, module: Identifier("object_basics"), name: Identifier("NewValueEvent"), type_params: [] }, contents: [20, 0, 0, 0, 0, 0, 0, 0] }
events: CoinBalanceChange { package_id: sui, transaction_module: Identifier("gas"), sender: B, change_type: Gas, owner: AddressOwner(B), coin_type: "sui::sui::SUI", coin_object_id: fake(111), version: SequenceNumber(1), amount: -182 }, MutateObject { package_id: test, transaction_module: Identifier("object_basics"), sender: B, object_type: "test::object_basics::Object", object_id: fake(107), version: SequenceNumber(4) }, MutateObject { package_id: sui, transaction_module: Identifier("unused_input_object"), sender: B, object_type: "test::object_basics::Object", object_id: fake(110), version: SequenceNumber(4) }, MoveEvent { package_id: test, transaction_module: Identifier("object_basics"), sender: B, type_: StructTag { address: test, module: Identifier("object_basics"), name: Identifier("NewValueEvent"), type_params: [] }, contents: [20, 0, 0, 0, 0, 0, 0, 0] }
written: object(107), object(110), object(111)

task 8 'run'. lines 84-84:
Expand Down
12 changes: 2 additions & 10 deletions crates/sui-core/src/transaction_input_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,15 @@ async fn get_gas_status(
};
let extra_gas_object_refs = gas_object_refs.into_iter().skip(1).collect();

let mut gas_status = check_gas(
check_gas(
store,
gas_object_ref,
transaction.gas_budget,
transaction.gas_price,
&transaction.kind,
extra_gas_object_refs,
)
.await?;

if transaction.contains_shared_object() {
// It's important that we do this here to make sure there is enough
// gas to cover shared objects, before we lock all objects.
gas_status.charge_consensus()?;
}

Ok(gas_status)
.await
}

#[instrument(level = "trace", skip_all)]
Expand Down
4 changes: 2 additions & 2 deletions crates/sui-core/src/unit_tests/gas_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ async fn test_transfer_sui_insufficient_gas() {
let (sender, sender_key): (_, AccountKeyPair) = get_key_pair();
let recipient = dbg_addr(2);
let gas_object_id = ObjectID::random();
let gas_object = Object::with_id_owner_gas_for_testing(gas_object_id, sender, 50);
let gas_object = Object::with_id_owner_gas_for_testing(gas_object_id, sender, 110);
let gas_object_ref = gas_object.compute_object_reference();
let authority_state = init_state().await;
authority_state.insert_genesis_object(gas_object).await;
Expand All @@ -172,7 +172,7 @@ async fn test_transfer_sui_insufficient_gas() {
recipient,
amount: None,
}));
let data = TransactionData::new_with_gas_price(kind, sender, gas_object_ref, 50, 1);
let data = TransactionData::new_with_gas_price(kind, sender, gas_object_ref, 110, 1);
let tx = to_sender_signed_transaction(data, &sender_key);

let effects = send_and_confirm_transaction(&authority_state, tx)
Expand Down
8 changes: 4 additions & 4 deletions crates/sui-core/src/unit_tests/pay_sui_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ use sui_types::{
#[tokio::test]
async fn test_pay_sui_failure_empty_recipients() {
let (sender, sender_key): (_, AccountKeyPair) = get_key_pair();
let coin1 = Object::with_id_owner_gas_for_testing(ObjectID::random(), sender, 1000);
let coin1 = Object::with_id_owner_gas_for_testing(ObjectID::random(), sender, 1100);

let res = execute_pay_sui(vec![coin1], vec![], vec![], sender, sender_key, 100).await;
let res = execute_pay_sui(vec![coin1], vec![], vec![], sender, sender_key, 1100).await;

let effects = res.txn_result.unwrap().signed_effects.unwrap().into_data();
assert_eq!(
Expand All @@ -35,15 +35,15 @@ async fn test_pay_sui_failure_arity_mismatch() {
let (sender, sender_key): (_, AccountKeyPair) = get_key_pair();
let recipient1 = dbg_addr(1);
let recipient2 = dbg_addr(2);
let coin1 = Object::with_id_owner_gas_for_testing(ObjectID::random(), sender, 1000);
let coin1 = Object::with_id_owner_gas_for_testing(ObjectID::random(), sender, 1110);

let res = execute_pay_sui(
vec![coin1],
vec![recipient1, recipient2],
vec![10],
sender,
sender_key,
100,
1100,
)
.await;

Expand Down
12 changes: 4 additions & 8 deletions crates/sui-cost/src/estimator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,7 @@ fn estimate_transaction_inner<S>(

// Step 1: charge min tx fee : can be computed precisely
gas_status.charge_min_tx_gas()?;
// Step 2: if contains shared objs, charge consensus fee : can be computed precisely
if tx.shared_input_objects().next().is_some() {
gas_status.charge_consensus()?;
}
// Step 3: charge storage read for all input objects : can be computed precisely
// Step 2: charge storage read for all input objects : can be computed precisely
// Dummy gas obj
let gas_obj = GasCoin::new(ObjectID::random(), 0).to_object(SequenceNumber::new());
let mut total_input_obj_size: usize = temporary_store
Expand All @@ -96,7 +92,7 @@ fn estimate_transaction_inner<S>(
total_input_obj_size += gas_obj.object_size_for_gas_metering();
gas_status.charge_storage_read(total_input_obj_size)?;

// Steps 4 & 5
// Steps 3 & 4
for single_tx in tx.single_transactions() {
match single_tx {
SingleTransactionKind::Publish(module) => {
Expand All @@ -111,11 +107,11 @@ fn estimate_transaction_inner<S>(
gas_status.charge_vm_gas()?;
}

// The assumption here is that size number of output objects is roughly double at most
// TODO: The assumption here is that size number of output objects is roughly double at most
// This assumption is not based on any real data. Feedback is welcomed
let mutated_object_sizes_after = mutated_object_sizes_after.unwrap_or(total_input_obj_size * 2);

// Step 6: charge for mutations, deletions, rebates: cannot be computed precisely, will approx
// Step 5: charge for mutations, deletions, rebates: cannot be computed precisely, will approx
// At this point we need to estimate the effects of mutating objects after execution
// We need to use some approx this
gas_status.charge_storage_mutation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,47 @@ expression: common_costs_estimate
---
{
"MergeCoin": {
"computation_cost": 6250,
"computation_cost": 6450,
"storage_cost": 9228,
"storage_rebate": 0
},
"Publish": {
"computation_cost": 7042,
"computation_cost": 7242,
"storage_cost": 10333,
"storage_rebate": 0
},
"SharedCounterAssertValue": {
"computation_cost": 668,
"computation_cost": 768,
"storage_cost": 811,
"storage_rebate": 0
},
"SharedCounterCreate": {
"computation_cost": 547,
"computation_cost": 747,
"storage_cost": 779,
"storage_rebate": 0
},
"SharedCounterIncrement": {
"computation_cost": 668,
"computation_cost": 768,
"storage_cost": 811,
"storage_rebate": 0
},
"SplitCoin": {
"computation_cost": 6228,
"computation_cost": 6428,
"storage_cost": 9196,
"storage_rebate": 0
},
"TransferPortionSuiCoin": {
"computation_cost": 56,
"computation_cost": 256,
"storage_cost": 52,
"storage_rebate": 0
},
"TransferWholeCoin": {
"computation_cost": 77,
"computation_cost": 277,
"storage_cost": 84,
"storage_rebate": 0
},
"TransferWholeSuiCoin": {
"computation_cost": 56,
"computation_cost": 256,
"storage_cost": 52,
"storage_rebate": 0
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ expression: common_costs_actual
---
{
"MergeCoin": {
"computation_cost": 63,
"computation_cost": 163,
"storage_cost": 32,
"storage_rebate": 0
},
"Publish": {
"computation_cost": 226,
"computation_cost": 326,
"storage_cost": 119,
"storage_rebate": 0
},
Expand All @@ -19,7 +19,7 @@ expression: common_costs_actual
"storage_rebate": 15
},
"SharedCounterCreate": {
"computation_cost": 102,
"computation_cost": 202,
"storage_cost": 31,
"storage_rebate": 0
},
Expand All @@ -29,22 +29,22 @@ expression: common_costs_actual
"storage_rebate": 15
},
"SplitCoin": {
"computation_cost": 173,
"computation_cost": 273,
"storage_cost": 80,
"storage_rebate": 0
},
"TransferPortionSuiCoin": {
"computation_cost": 45,
"computation_cost": 145,
"storage_cost": 48,
"storage_rebate": 0
},
"TransferWholeCoin": {
"computation_cost": 41,
"computation_cost": 141,
"storage_cost": 32,
"storage_rebate": 0
},
"TransferWholeSuiCoin": {
"computation_cost": 39,
"computation_cost": 139,
"storage_cost": 32,
"storage_rebate": 0
}
Expand Down
12 changes: 4 additions & 8 deletions crates/sui-protocol-constants/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,16 @@ pub const MAX_NUM_EVENT_EMIT: u64 = 256;
// note: per-instruction and native function gas costs live in the sui-cost-tables crate

/// Base cost for any Sui transaction
pub const BASE_TX_COST_FIXED: u64 = 10_000;
pub const BASE_TX_COST_FIXED: u64 = 110_000;

/// Additional cost for Move call transactions that use a shared object.
/// i.e., the base cost of such a transaction is BASE_TX_COST_FIXED + CONSENSUS_COST
pub const CONSENSUS_COST: u64 = 100_000;
/// Additional cost for a transaction that publishes a package
/// i.e., the base cost of such a transaction is BASE_TX_COST_FIXED + PACKAGE_PUBLISH_COST_FIXED
pub const PACKAGE_PUBLISH_COST_FIXED: u64 = 1_000;

/// Cost per byte of a Move call transaction
/// i.e., the cost of such a transaction is base_cost + (BASE_TX_COST_PER_BYTE * size)
pub const BASE_TX_COST_PER_BYTE: u64 = 0;

/// Additional cost for a transaction that publishes a package
/// i.e., the base cost of such a transaction is BASE_TX_COST_FIXED + PACKAGE_PUBLISH_COST_FIXED
pub const PACKAGE_PUBLISH_COST_FIXED: u64 = 1_000;

/// Cost per byte for a transaction that publishes a package
pub const PACKAGE_PUBLISH_COST_PER_BYTE: u64 = 80;

Expand Down
9 changes: 0 additions & 9 deletions crates/sui-types/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,6 @@ pub struct SuiCostTable {
/// Per byte cost to write objects to the store. This is computation cost instead of
/// storage cost because it does not change the amount of data stored on the db.
pub object_mutation_per_byte_cost: ComputationCostPerByte,
/// Cost to use shared objects in a transaction, which requires full consensus.
pub consensus_cost: FixedCost,

/// Unit cost of a byte in the storage. This will be used both for charging for
/// new storage as well as rebating for deleting storage. That is, we expect users to
/// get full refund on the object storage when it's deleted.
Expand All @@ -181,8 +178,6 @@ pub static INIT_SUI_COST_TABLE: Lazy<SuiCostTable> = Lazy::new(|| SuiCostTable {
package_publish_per_byte_cost: ComputationCostPerByte::new(PACKAGE_PUBLISH_COST_PER_BYTE),
object_read_per_byte_cost: ComputationCostPerByte::new(OBJ_ACCESS_COST_READ_PER_BYTE),
object_mutation_per_byte_cost: ComputationCostPerByte::new(OBJ_ACCESS_COST_MUTATE_PER_BYTE),
consensus_cost: FixedCost::new(CONSENSUS_COST),

storage_per_byte_cost: StorageCostPerByte::new(OBJ_DATA_COST_REFUNDABLE),
});

Expand Down Expand Up @@ -253,10 +248,6 @@ impl<'a> SuiGasStatus<'a> {
self.deduct_computation_cost(INIT_SUI_COST_TABLE.min_transaction_cost.deref())
}

pub fn charge_consensus(&mut self) -> Result<(), ExecutionError> {
self.deduct_computation_cost(&INIT_SUI_COST_TABLE.consensus_cost)
}

pub fn charge_publish_package(&mut self, size: usize) -> Result<(), ExecutionError> {
let computation_cost =
NumBytes::new(size as u64).mul(*INIT_SUI_COST_TABLE.package_publish_per_byte_cost);
Expand Down

0 comments on commit ae3f487

Please sign in to comment.