Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
MitchTurner committed Feb 8, 2024
1 parent 92c0040 commit e8ae067
Show file tree
Hide file tree
Showing 11 changed files with 47 additions and 35 deletions.
16 changes: 8 additions & 8 deletions fuel-tx/src/transaction/consensus_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,23 +136,23 @@ impl ConsensusParameters {
#[cfg_attr(feature = "serde", serde(default))]
pub struct FeeParameters {
/// Factor to convert between gas and transaction assets value.
pub gas_price_factor: u64,
// pub gas_price_factor: u64,
/// A fixed ratio linking metered bytes to gas price
pub gas_per_byte: u64,
}

impl FeeParameters {
/// Default consensus parameters with settings suggested in fuel-specs
pub const DEFAULT: Self = Self {
gas_price_factor: 1_000_000_000,
// gas_price_factor: 1_000_000_000,
gas_per_byte: 4,
};

/// Replace the gas price factor with the given argument
pub const fn with_gas_price_factor(mut self, gas_price_factor: u64) -> Self {
self.gas_price_factor = gas_price_factor;
self
}
// /// Replace the gas price factor with the given argument
// pub const fn with_gas_price_factor(mut self, gas_price_factor: u64) -> Self {
// self.gas_price_factor = gas_price_factor;
// self
// }

pub const fn with_gas_per_byte(mut self, gas_per_byte: u64) -> Self {
self.gas_per_byte = gas_per_byte;
Expand Down Expand Up @@ -420,7 +420,7 @@ pub mod default_parameters {

pub const MAX_GAS_PER_PREDICATE: u64 =
PredicateParameters::DEFAULT.max_gas_per_predicate;
pub const GAS_PRICE_FACTOR: u64 = FeeParameters::DEFAULT.gas_price_factor;
// pub const GAS_PRICE_FACTOR: u64 = FeeParameters::DEFAULT.gas_price_factor;
pub const GAS_PER_BYTE: u64 = FeeParameters::DEFAULT.gas_per_byte;

pub const CHAIN_ID: ChainId = ChainId::new(0);
Expand Down
28 changes: 12 additions & 16 deletions fuel-tx/src/transaction/fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,15 @@ impl TransactionFee {
gas_costs: &GasCosts,
params: &FeeParameters,
tx: &T,
gas_price: u64,
) -> Option<Self>
where
T: Chargeable,
{
let min_gas = tx.min_gas(gas_costs, params);
let max_gas = tx.max_gas(gas_costs, params);
let min_fee = tx.min_fee(gas_costs, params).try_into().ok()?;
let max_fee = tx.max_fee(gas_costs, params).try_into().ok()?;
let min_fee = tx.min_fee(gas_costs, params, gas_price).try_into().ok()?;
let max_fee = tx.max_fee(gas_costs, params, gas_price).try_into().ok()?;

if min_fee > max_fee {
return None
Expand Down Expand Up @@ -152,23 +153,15 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies {
}

/// Returns the minimum fee required to start transaction execution.
fn min_fee(&self, gas_costs: &GasCosts, fee: &FeeParameters) -> u128 {
gas_to_fee(
self.min_gas(gas_costs, fee),
self.price(),
fee.gas_price_factor,
)
fn min_fee(&self, gas_costs: &GasCosts, fee: &FeeParameters, gas_price: u64) -> u128 {
gas_to_fee(self.min_gas(gas_costs, fee), self.price(), gas_price)
}

/// Returns the maximum possible fee after the end of transaction execution.
///
/// The function guarantees that the value is not less than [Self::min_fee].
fn max_fee(&self, gas_costs: &GasCosts, fee: &FeeParameters) -> u128 {
gas_to_fee(
self.max_gas(gas_costs, fee),
self.price(),
fee.gas_price_factor,
)
fn max_fee(&self, gas_costs: &GasCosts, fee: &FeeParameters, gas_price: u64) -> u128 {
gas_to_fee(self.max_gas(gas_costs, fee), self.price(), gas_price)
}

/// Returns the fee amount that can be refunded back based on the `used_gas` and
Expand All @@ -180,15 +173,18 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies {
gas_costs: &GasCosts,
fee: &FeeParameters,
used_gas: Word,
gas_price: u64,
) -> Option<Word> {
// We've already charged the user for witnesses as part of the minimal gas and all
// execution required to validate transaction validity rules.
let min_gas = self.min_gas(gas_costs, fee);

let total_used_gas = min_gas.saturating_add(used_gas);
let used_fee = gas_to_fee(total_used_gas, self.price(), fee.gas_price_factor);
let used_fee = gas_to_fee(total_used_gas, self.price(), gas_price);

let refund = self.max_fee(gas_costs, fee).saturating_sub(used_fee);
let refund = self
.max_fee(gas_costs, fee, gas_price)
.saturating_sub(used_fee);
// It is okay to saturate everywhere above because it only can decrease the value
// of `refund`. But here, because we need to return the amount we
// want to refund, we need to handle the overflow caused by the price.
Expand Down
3 changes: 2 additions & 1 deletion fuel-tx/src/transaction/types/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ impl FormatValidityChecks for Create {
&self,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<(), ValidityError> {
let ConsensusParameters {
contract_params,
Expand All @@ -230,7 +231,7 @@ impl FormatValidityChecks for Create {
..
} = consensus_params;

check_common_part(self, block_height, consensus_params)?;
check_common_part(self, block_height, consensus_params, gas_price)?;

let bytecode_witness_len = self
.witnesses
Expand Down
1 change: 1 addition & 0 deletions fuel-tx/src/transaction/types/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ impl FormatValidityChecks for Mint {
&self,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<(), ValidityError> {
check_size(self, consensus_params.tx_params())?;

Expand Down
3 changes: 2 additions & 1 deletion fuel-tx/src/transaction/types/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,9 @@ impl FormatValidityChecks for Script {
&self,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<(), ValidityError> {
check_common_part(self, block_height, consensus_params)?;
check_common_part(self, block_height, consensus_params, gas_price)?;
let script_params = consensus_params.script_params();
if self.script.len() as u64 > script_params.max_script_length {
Err(ValidityError::TransactionScriptLength)?;
Expand Down
14 changes: 9 additions & 5 deletions fuel-tx/src/transaction/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,9 @@ pub trait FormatValidityChecks {
&self,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<(), ValidityError> {
self.check_without_signatures(block_height, consensus_params)?;
self.check_without_signatures(block_height, consensus_params, gas_price)?;
self.check_signatures(&consensus_params.chain_id())?;

Ok(())
Expand All @@ -263,6 +264,7 @@ pub trait FormatValidityChecks {
&self,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<(), ValidityError>;
}

Expand All @@ -279,16 +281,17 @@ impl FormatValidityChecks for Transaction {
&self,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<(), ValidityError> {
match self {
Transaction::Script(script) => {
script.check_without_signatures(block_height, consensus_params)
script.check_without_signatures(block_height, consensus_params, gas_price)
}
Transaction::Create(create) => {
create.check_without_signatures(block_height, consensus_params)
create.check_without_signatures(block_height, consensus_params, gas_price)
}
Transaction::Mint(mint) => {
mint.check_without_signatures(block_height, consensus_params)
mint.check_without_signatures(block_height, consensus_params, gas_price)
}
}
}
Expand All @@ -313,6 +316,7 @@ pub(crate) fn check_common_part<T>(
tx: &T,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<(), ValidityError>
where
T: canonical::Serialize + Chargeable + field::Outputs,
Expand Down Expand Up @@ -349,7 +353,7 @@ where
}

if let Some(max_fee_limit) = tx.policies().get(PolicyType::MaxFee) {
if tx.max_fee(gas_costs, fee_params) > max_fee_limit as u128 {
if tx.max_fee(gas_costs, fee_params, gas_price) > max_fee_limit as u128 {
Err(ValidityError::TransactionMaxFeeLimitExceeded)?
}
}
Expand Down
4 changes: 3 additions & 1 deletion fuel-vm/src/checked_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,13 @@ pub trait IntoChecked: FormatValidityChecks + Sized {
self,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<Checked<Self>, CheckError>
where
Checked<Self>: CheckPredicates,
{
let check_predicate_params = consensus_params.into();
self.into_checked_basic(block_height, consensus_params)?
self.into_checked_basic(block_height, consensus_params, gas_price)?
.check_signatures(&consensus_params.chain_id)?
.check_predicates(&check_predicate_params)
}
Expand All @@ -207,6 +208,7 @@ pub trait IntoChecked: FormatValidityChecks + Sized {
self,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<Checked<Self>, CheckError>;
}

Expand Down
3 changes: 2 additions & 1 deletion fuel-vm/src/checked_transaction/balances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub(crate) fn initial_free_balances<T>(
gas_costs: &GasCosts,
params: &FeeParameters,
base_asset_id: &AssetId,
gas_price: u64,
) -> Result<AvailableBalances, ValidityError>
where
T: Chargeable + field::Inputs + field::Outputs,
Expand Down Expand Up @@ -67,7 +68,7 @@ where
}

// Deduct fee from base asset
let fee = TransactionFee::checked_from_tx(gas_costs, params, transaction)
let fee = TransactionFee::checked_from_tx(gas_costs, params, transaction, gas_price)
.ok_or(ValidityError::BalanceOverflow)?;

let base_asset_balance = non_retryable_balances.entry(*base_asset_id).or_default();
Expand Down
5 changes: 4 additions & 1 deletion fuel-vm/src/checked_transaction/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ pub mod create {
mut self,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<Checked<Self>, CheckError> {
let chain_id = consensus_params.chain_id();
self.precompute(&chain_id)?;
self.check_without_signatures(block_height, consensus_params)?;
self.check_without_signatures(block_height, consensus_params, gas_price)?;

// validate fees and compute free balances
let AvailableBalances {
Expand Down Expand Up @@ -202,6 +203,7 @@ pub mod script {
mut self,
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
gas_price: u64,
) -> Result<Checked<Self>, CheckError> {
let chain_id = consensus_params.chain_id();
self.precompute(&chain_id)?;
Expand All @@ -217,6 +219,7 @@ pub mod script {
consensus_params.gas_costs(),
consensus_params.fee_params(),
consensus_params.base_asset_id(),
gas_price,
)?;

let metadata = CheckedMetadata {
Expand Down
3 changes: 2 additions & 1 deletion fuel-vm/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,12 +424,13 @@ pub trait ExecutableTransaction:
gas_costs: &GasCosts,
fee_params: &FeeParameters,
base_asset_id: &AssetId,
gas_price: u64,
) -> Result<(), ValidityError>
where
I: for<'a> Index<&'a AssetId, Output = Word>,
{
let gas_refund = self
.refund_fee(gas_costs, fee_params, used_gas)
.refund_fee(gas_costs, fee_params, used_gas, gas_price)
.ok_or(ValidityError::GasCostsCoinsOverflow)?;

self.outputs_mut().iter_mut().try_for_each(|o| match o {
Expand Down
2 changes: 2 additions & 0 deletions fuel-vm/src/interpreter/post_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ where
used_gas: Word,
initial_balances: &InitialBalances,
balances: &RuntimeBalances,
gas_price: u64,
) -> Result<(), RuntimeError<S::DataError>>
where
Tx: ExecutableTransaction,
Expand All @@ -58,6 +59,7 @@ where
gas_costs,
fee_params,
base_asset_id,
gas_price,
)
.map_err(|e| Bug::new(BugVariant::UncomputableRefund).with_message(e))?;

Expand Down

0 comments on commit e8ae067

Please sign in to comment.