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

feat: Configurable Base Asset ID #573

Merged
merged 20 commits into from
Sep 7, 2023
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

#### Breaking

- [#573](https://github.com/FuelLabs/fuel-vm/pull/573): Added `base_asset_id` as a required field to `FeeParameters`. `base_asset_id` is used to supply the ID of the base asset.
- [#554](https://github.com/FuelLabs/fuel-vm/pull/554): Removed `debug` feature from the `fuel-vm`. The debugger is always available and becomes active after calling any `set_*` method.
- [#537](https://github.com/FuelLabs/fuel-vm/pull/537): Use dependent cost for `k256`, `s256`, `mcpi`, `scwq`, `swwq` opcodes.
These opcodes charged inadequately low costs in comparison to the amount of work.
Expand Down
6 changes: 6 additions & 0 deletions fuel-tx/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use crate::Signable;

use fuel_crypto::SecretKey;
use fuel_types::{
AssetId,
BlockHeight,
ChainId,
Nonce,
Expand Down Expand Up @@ -276,6 +277,11 @@ impl<Tx> TransactionBuilder<Tx> {
self
}

pub fn with_base_asset_id(&mut self, base_asset_id: AssetId) -> &mut Self {
self.params.base_asset_id = base_asset_id;
self
}

pub fn with_gas_costs(&mut self, gas_costs: GasCosts) -> &mut Self {
self.params.gas_costs = gas_costs;
self
Expand Down
3 changes: 2 additions & 1 deletion fuel-tx/src/tests/offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use fuel_types::{
Deserialize,
SerializedSize,
},
AssetId,
ChainId,
};
use rand::{
Expand Down Expand Up @@ -87,7 +88,7 @@ fn common_parts_create_and_script<Tx: Buildable>(
assert_eq!(owner, owner_p);
}

if let Some(asset_id) = i.asset_id() {
if let Some(asset_id) = i.asset_id(&AssetId::BASE) {
// Message doesn't store `AssetId` explicitly but works with base asset
if let Some(offset) = i.repr().asset_id_offset() {
cases.asset_id = true;
Expand Down
1 change: 1 addition & 0 deletions fuel-tx/src/tests/valid_cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub fn test_params() -> ConsensusParameters {
FEE_PARAMS,
CHAIN_ID,
Default::default(),
Default::default(),
)
}

Expand Down
14 changes: 10 additions & 4 deletions fuel-tx/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,10 @@ impl Transaction {

pub trait Executable: field::Inputs + field::Outputs + field::Witnesses {
/// Returns the assets' ids used in the inputs in the order of inputs.
fn input_asset_ids(&self) -> IntoIter<&AssetId> {
fn input_asset_ids<'a>(
&'a self,
base_asset_id: &'a AssetId,
) -> IntoIter<&'a AssetId> {
self.inputs()
.iter()
.filter_map(|input| match input {
Expand All @@ -275,16 +278,19 @@ pub trait Executable: field::Inputs + field::Outputs + field::Witnesses {
Input::MessageCoinSigned(_)
| Input::MessageCoinPredicate(_)
| Input::MessageDataPredicate(_)
| Input::MessageDataSigned(_) => Some(&AssetId::BASE),
| Input::MessageDataSigned(_) => Some(base_asset_id),
_ => None,
})
.collect_vec()
.into_iter()
}

/// Returns unique assets' ids used in the inputs.
fn input_asset_ids_unique(&self) -> IntoIter<&AssetId> {
let asset_ids = self.input_asset_ids();
fn input_asset_ids_unique<'a>(
&'a self,
base_asset_id: &'a AssetId,
) -> IntoIter<&'a AssetId> {
let asset_ids = self.input_asset_ids(base_asset_id);

#[cfg(feature = "std")]
let asset_ids = asset_ids.unique();
Expand Down
9 changes: 9 additions & 0 deletions fuel-tx/src/transaction/consensus_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub struct ConsensusParameters {
pub fee_params: FeeParameters,
pub chain_id: ChainId,
pub gas_costs: GasCosts,
pub base_asset_id: AssetId,
}

impl Default for ConsensusParameters {
Expand All @@ -47,6 +48,7 @@ impl ConsensusParameters {
fee_params: FeeParameters::DEFAULT,
chain_id: ChainId::default(),
gas_costs: GasCosts::default(),
base_asset_id: Default::default(),
}
}

Expand All @@ -60,6 +62,7 @@ impl ConsensusParameters {
fee_params: FeeParameters::DEFAULT,
chain_id,
gas_costs: GasCosts::default(),
base_asset_id: Default::default(),
}
}

Expand All @@ -72,6 +75,7 @@ impl ConsensusParameters {
fee_params: FeeParameters,
chain_id: ChainId,
gas_costs: GasCosts,
base_asset_id: AssetId,
) -> Self {
Self {
tx_params,
Expand All @@ -81,6 +85,7 @@ impl ConsensusParameters {
fee_params,
chain_id,
gas_costs,
base_asset_id,
}
}

Expand Down Expand Up @@ -109,6 +114,10 @@ impl ConsensusParameters {
&self.fee_params
}

pub fn base_asset_id(&self) -> &AssetId {
&self.base_asset_id
}

/// Get the chain ID
pub fn chain_id(&self) -> ChainId {
self.chain_id
Expand Down
23 changes: 14 additions & 9 deletions fuel-tx/src/transaction/types/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ use crate::{
ConsensusParameters,
};

use fuel_types::AssetId;

use crate::{
transaction::field::{
BytecodeLength,
Expand Down Expand Up @@ -225,11 +223,21 @@ impl FormatValidityChecks for Create {
block_height: BlockHeight,
consensus_params: &ConsensusParameters,
) -> Result<(), CheckError> {
let ConsensusParameters {
tx_params,
predicate_params,
contract_params,
chain_id,
base_asset_id,
..
} = consensus_params;

check_common_part(
self,
block_height,
consensus_params.tx_params(),
consensus_params.predicate_params(),
tx_params,
predicate_params,
base_asset_id,
)?;

let bytecode_witness_len = self
Expand All @@ -238,8 +246,6 @@ impl FormatValidityChecks for Create {
.map(|w| w.as_ref().len() as Word)
.ok_or(CheckError::TransactionCreateBytecodeWitnessIndex)?;

let contract_params = consensus_params.contract_params();

if bytecode_witness_len > contract_params.contract_max_size
|| bytecode_witness_len / 4 != self.bytecode_length
{
Expand Down Expand Up @@ -285,8 +291,7 @@ impl FormatValidityChecks for Create {
} else {
#[cfg(feature = "std")]
{
let metadata =
CreateMetadata::compute(self, &consensus_params.chain_id())?;
let metadata = CreateMetadata::compute(self, chain_id)?;
(metadata.state_root, metadata.contract_id)
}

Expand Down Expand Up @@ -315,7 +320,7 @@ impl FormatValidityChecks for Create {
Err(CheckError::TransactionCreateOutputVariable { index })
}

Output::Change { asset_id, .. } if asset_id != &AssetId::BASE => {
Output::Change { asset_id, .. } if asset_id != base_asset_id => {
Err(CheckError::TransactionCreateOutputChangeNotBaseAsset { index })
}

Expand Down
7 changes: 5 additions & 2 deletions fuel-tx/src/transaction/types/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,14 +432,17 @@ impl Input {
}
}

pub const fn asset_id(&self) -> Option<&AssetId> {
pub const fn asset_id<'a>(
&'a self,
base_asset_id: &'a AssetId,
) -> Option<&'a AssetId> {
match self {
Input::CoinSigned(CoinSigned { asset_id, .. })
| Input::CoinPredicate(CoinPredicate { asset_id, .. }) => Some(asset_id),
Input::MessageCoinSigned(_)
| Input::MessageCoinPredicate(_)
| Input::MessageDataSigned(_)
| Input::MessageDataPredicate(_) => Some(&AssetId::BASE),
| Input::MessageDataPredicate(_) => Some(base_asset_id),
Input::Contract(_) => None,
}
}
Expand Down
1 change: 1 addition & 0 deletions fuel-tx/src/transaction/types/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ impl FormatValidityChecks for Script {
block_height,
consensus_params.tx_params(),
consensus_params.predicate_params(),
consensus_params.base_asset_id(),
)?;
let script_params = consensus_params.script_params();
if self.script.len() > script_params.max_script_length as usize {
Expand Down
54 changes: 29 additions & 25 deletions fuel-tx/src/transaction/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ pub(crate) fn check_common_part<T>(
block_height: BlockHeight,
tx_params: &TxParameters,
predicate_params: &PredicateParameters,
base_asset_id: &AssetId,
) -> Result<(), CheckError>
where
T: field::GasPrice
Expand Down Expand Up @@ -352,30 +353,33 @@ where
Err(CheckError::NoSpendableInput)?
}

tx.input_asset_ids_unique().try_for_each(|input_asset_id| {
// check for duplicate change outputs
if tx
.outputs()
.iter()
.filter_map(|output| match output {
Output::Change { asset_id, .. } if input_asset_id == asset_id => Some(()),
Output::Change { asset_id, .. }
if asset_id != &AssetId::default() && input_asset_id == asset_id =>
{
Some(())
}
_ => None,
})
.count()
> 1
{
return Err(CheckError::TransactionOutputChangeAssetIdDuplicated(
*input_asset_id,
))
}
tx.input_asset_ids_unique(base_asset_id)
.try_for_each(|input_asset_id| {
// check for duplicate change outputs
if tx
.outputs()
.iter()
.filter_map(|output| match output {
Output::Change { asset_id, .. } if input_asset_id == asset_id => {
Some(())
}
Output::Change { asset_id, .. }
if asset_id != base_asset_id && input_asset_id == asset_id =>
{
Some(())
}
_ => None,
})
.count()
> 1
{
return Err(CheckError::TransactionOutputChangeAssetIdDuplicated(
*input_asset_id,
))
}

Ok(())
})?;
Ok(())
})?;

// Check for duplicated input utxo id
let duplicated_utxo_id = tx
Expand Down Expand Up @@ -421,7 +425,7 @@ where

if let Output::Change { asset_id, .. } = output {
if !tx
.input_asset_ids()
.input_asset_ids(base_asset_id)
.any(|input_asset_id| input_asset_id == asset_id)
{
return Err(CheckError::TransactionOutputChangeAssetIdNotFound(
Expand All @@ -432,7 +436,7 @@ where

if let Output::Coin { asset_id, .. } = output {
if !tx
.input_asset_ids()
.input_asset_ids(base_asset_id)
.any(|input_asset_id| input_asset_id == asset_id)
{
return Err(CheckError::TransactionOutputCoinAssetIdNotFound(
Expand Down
1 change: 0 additions & 1 deletion fuel-types/src/array_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,6 @@ impl ContractId {
}

impl AssetId {
/// The base native asset of the Fuel protocol.
pub const BASE: AssetId = AssetId::zeroed();
}

Expand Down
Loading