Skip to content

Commit

Permalink
feat: Configurable Base Asset ID (#573)
Browse files Browse the repository at this point in the history
* Add `base_aseset_id` to FeeParameters

* Remove `AssetId::BASE`

* Pipe AssetId to Message Inputs

* Add base_asset_id to `RetryableAmount` and `input_asset_id`

* Update tests

* Update sizes.rs

* Remove unused assetid references

* Update smo_tests.rs

* Update

* Update CHANGELOG.md

* Clean up lib.rs

* Update message.rs

* Use consistent rng seed

* Remove `AssetId::default` from production flows

* Update full change test

* Clippy

* Move base_asset_id to consensus params top level

---------

Co-authored-by: Hannes Karppila <hannes.karppila@gmail.com>
  • Loading branch information
Brandon Vrooman and Dentosal authored Sep 7, 2023
1 parent 680e240 commit 5030f96
Show file tree
Hide file tree
Showing 25 changed files with 238 additions and 102 deletions.
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

0 comments on commit 5030f96

Please sign in to comment.