Skip to content

Commit

Permalink
Add Gas price to transaction (MystenLabs#2501)
Browse files Browse the repository at this point in the history
Add Gas price to transaction
  • Loading branch information
mohanzz authored Jun 14, 2022
1 parent 75d7642 commit d96ea49
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 14 deletions.
10 changes: 8 additions & 2 deletions crates/sui-core/src/transaction_input_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use tracing::{debug, instrument};

use crate::authority::SuiDataStore;

// TODO: read this from onchain source (e.g. SystemState)
const STORAGE_GAS_PRICE: u64 = 1;
pub struct InputObjects {
objects: Vec<(InputObjectKind, Object)>,
}
Expand Down Expand Up @@ -113,6 +115,7 @@ where
store,
transaction.gas_payment_object_ref().0,
transaction.data.gas_budget,
transaction.data.gas_price,
transaction.data.kind.is_system_tx(),
)
.await?;
Expand All @@ -139,6 +142,7 @@ async fn check_gas<const A: bool, S>(
store: &SuiDataStore<A, S>,
gas_payment_id: ObjectID,
gas_budget: u64,
computation_gas_price: u64,
is_system_tx: bool,
) -> SuiResult<SuiGasStatus<'static>>
where
Expand All @@ -151,9 +155,11 @@ where
let gas_object = gas_object.ok_or(SuiError::ObjectNotFound {
object_id: gas_payment_id,
})?;
gas::check_gas_balance(&gas_object, gas_budget)?;
let gas_price = std::cmp::max(computation_gas_price, STORAGE_GAS_PRICE);
gas::check_gas_balance(&gas_object, gas_budget, gas_price)?;
// TODO: Pass in real computation gas unit price and storage gas unit price.
let gas_status = gas::start_gas_metering(gas_budget, 1, 1)?;
let gas_status =
gas::start_gas_metering(gas_budget, computation_gas_price, STORAGE_GAS_PRICE)?;
Ok(gas_status)
}
}
Expand Down
67 changes: 58 additions & 9 deletions crates/sui-core/src/unit_tests/gas_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,17 @@ async fn test_tx_gas_balance_less_than_budget() {
// during handle transaction phase.
let gas_balance = *MIN_GAS_BUDGET - 1;
let budget = *MIN_GAS_BUDGET;
let result = execute_transfer(gas_balance, budget, false).await;
let gas_price = 1;
let result = execute_transfer_with_price(gas_balance, budget, gas_price, false).await;
let err = result.response.unwrap_err();
assert_eq!(
err,
SuiError::InsufficientGas {
error: format!(
"Gas balance is {}, not enough to pay {}",
gas_balance, budget
"Gas balance is {}, not enough to pay {} with gas price of {}",
gas_balance,
gas_price * budget,
gas_price
)
}
);
Expand Down Expand Up @@ -114,6 +117,44 @@ async fn test_native_transfer_sufficient_gas() -> SuiResult {
Ok(())
}

#[tokio::test]
async fn test_native_transfer_gas_price_is_used() {
let gas_price_1 = 1;
let gas_price_2 = gas_price_1 * 2;
let result =
execute_transfer_with_price(*MAX_GAS_BUDGET, *MAX_GAS_BUDGET, gas_price_1, true).await;
let effects = result.response.unwrap().signed_effects.unwrap().effects;
let gas_summary_1 = effects.status.gas_cost_summary();

let result =
execute_transfer_with_price(*MAX_GAS_BUDGET, *MAX_GAS_BUDGET / 2, gas_price_2, true).await;
let effects = result.response.unwrap().signed_effects.unwrap().effects;
let gas_summary_2 = effects.status.gas_cost_summary();

assert_eq!(
gas_summary_1.computation_cost * 2,
gas_summary_2.computation_cost
);

// test overflow with insufficient gas
let gas_balance = *MAX_GAS_BUDGET;
let gas_budget = *MAX_GAS_BUDGET;
let gas_price = u64::MAX;
let result = execute_transfer_with_price(gas_balance, gas_budget, gas_price, true).await;
let err = result.response.unwrap_err();
assert_eq!(
err,
SuiError::InsufficientGas {
error: format!(
"Gas balance is {}, not enough to pay {} with gas price of {}",
gas_balance,
(gas_budget as u128) * (gas_price as u128),
gas_price
)
}
);
}

#[tokio::test]
async fn test_native_transfer_insufficient_gas_reading_objects() {
// This test creates a transfer transaction with a gas budget, that's more than
Expand Down Expand Up @@ -459,6 +500,15 @@ struct TransferResult {
}

async fn execute_transfer(gas_balance: u64, gas_budget: u64, run_confirm: bool) -> TransferResult {
execute_transfer_with_price(gas_balance, gas_budget, 1, run_confirm).await
}

async fn execute_transfer_with_price(
gas_balance: u64,
gas_budget: u64,
gas_price: u64,
run_confirm: bool,
) -> TransferResult {
let (sender, sender_key) = get_key_pair();
let object_id: ObjectID = ObjectID::random();
let recipient = dbg_addr(2);
Expand All @@ -473,13 +523,12 @@ async fn execute_transfer(gas_balance: u64, gas_budget: u64, run_confirm: bool)
.unwrap()
.unwrap();

let data = TransactionData::new_transfer(
let kind = TransactionKind::Single(SingleTransactionKind::TransferCoin(TransferCoin {
recipient,
object.compute_object_reference(),
sender,
gas_object_ref,
gas_budget,
);
object_ref: object.compute_object_reference(),
}));
let data =
TransactionData::new_with_gas_price(kind, sender, gas_object_ref, gas_budget, gas_price);
let signature = Signature::new(&data, &sender_key);
let tx = Transaction::new(data, signature);

Expand Down
7 changes: 4 additions & 3 deletions crates/sui-types/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ impl<'a> SuiGasStatus<'a> {
/// 2. If it's enough to pay the flat minimum transaction fee
/// 3. If it's less than the max gas budget allowed
/// 4. If the gas_object actually has enough balance to pay for the budget.
pub fn check_gas_balance(gas_object: &Object, gas_budget: u64) -> SuiResult {
pub fn check_gas_balance(gas_object: &Object, gas_budget: u64, gas_price: u64) -> SuiResult {
ok_or_gas_error!(
gas_object.is_owned(),
"Gas object must be owned Move object".to_owned()
Expand All @@ -320,9 +320,10 @@ pub fn check_gas_balance(gas_object: &Object, gas_budget: u64) -> SuiResult {
)?;

let balance = get_gas_balance(gas_object)?;
let total_amount: u128 = (gas_budget as u128) * (gas_price as u128);
ok_or_gas_error!(
balance >= gas_budget,
format!("Gas balance is {balance}, not enough to pay {gas_budget}")
(balance as u128) >= total_amount,
format!("Gas balance is {balance}, not enough to pay {total_amount} with gas price of {gas_price}")
)
}

Expand Down
18 changes: 18 additions & 0 deletions crates/sui-types/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ pub struct TransactionData {
pub kind: TransactionKind,
sender: SuiAddress,
gas_payment: ObjectRef,
pub gas_price: u64,
pub gas_budget: u64,
}

Expand All @@ -318,6 +319,23 @@ where
TransactionData {
kind,
sender,
gas_price: 1,
gas_payment,
gas_budget,
}
}

pub fn new_with_gas_price(
kind: TransactionKind,
sender: SuiAddress,
gas_payment: ObjectRef,
gas_budget: u64,
gas_price: u64,
) -> Self {
TransactionData {
kind,
sender,
gas_price,
gas_payment,
gas_budget,
}
Expand Down

0 comments on commit d96ea49

Please sign in to comment.