Skip to content
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8a6502c
Started work on the `assemble_tx` endpoint.
xgreenx Feb 26, 2025
a19bcc3
Implemented remaining logic
xgreenx Feb 27, 2025
8a5ff0c
fix: Updated integer types in client
netrome Feb 27, 2025
59bc96a
feat: Support assembleTx in client
netrome Feb 27, 2025
6d87183
fix: Use HexString instead of passing around Vec<u8>
netrome Feb 27, 2025
2a42e40
fix: Integer changes in tests
netrome Feb 27, 2025
1c3561d
fix: Typo
netrome Feb 27, 2025
04660bd
fix: Cleanup
netrome Feb 27, 2025
2da4546
Re-worked some tests to use new assemble tx API. ALong with it fixed …
xgreenx Feb 28, 2025
cdf2970
Merge branch 'refs/heads/master' into feature/assemble-tx
xgreenx Feb 28, 2025
30177d0
Updated CHANGELOG
xgreenx Feb 28, 2025
2bc6258
refactor: Tidy up `FuelCoreClientExt` trait
netrome Feb 28, 2025
7f7df62
refactor: Simplify control flow in assemble_transaction impl
netrome Feb 28, 2025
208f60b
refactor: Reorder trait methods
netrome Feb 28, 2025
7fd6d51
refactor: Tidy up `AssembleTx::new` logic
netrome Feb 28, 2025
0b38697
Remove breaking change from API
xgreenx Feb 28, 2025
f307ba5
Use GraphQL to produce a block, it awaits off-chain database to index…
xgreenx Feb 28, 2025
9eddbf9
feat: Don't use bool for `destroy` option
netrome Mar 3, 2025
a2942f1
fix: Remove unsafe array slicing
netrome Mar 3, 2025
2646e53
feat: Break out big loop to dedicated `populate_missing_contract_inpu…
netrome Mar 3, 2025
3885dee
Removed unnessesary cover tip step
xgreenx Mar 3, 2025
03b281e
We still need to cover fee because fake coin doesn't have any amount …
xgreenx Mar 3, 2025
14ecbce
Added protection over many estimation of predicates
xgreenx Mar 3, 2025
a6963e7
Merge branch 'master' into feature/assemble-tx
xgreenx Mar 3, 2025
25d26d7
Merge branch 'master' into feature/assemble-tx
AurelienFT Mar 4, 2025
71d5b1e
Fix tests compilation
AurelienFT Mar 4, 2025
c8c1e49
Fixed witness index
xgreenx Mar 4, 2025
d118248
Fixed the issues with custom witness limit.
xgreenx Mar 4, 2025
00fda90
Merge branch 'master' into feature/assemble-tx
xgreenx Mar 4, 2025
28a3c10
Include `gas_price` into the response.
xgreenx Mar 4, 2025
eb7aa08
Fixed wrong `used_gas` calculation logic
xgreenx Mar 4, 2025
dfa5e81
Added filling of missing witnesses
xgreenx Mar 5, 2025
78c1e4c
Merge branch 'refs/heads/master' into feature/assemble-tx
xgreenx Mar 6, 2025
af19011
Resolved conflicts
xgreenx Mar 6, 2025
269ab9f
Make CI happy
xgreenx Mar 6, 2025
c2e215a
Make CI happy
xgreenx Mar 6, 2025
c86be0a
Fixed flaky test
xgreenx Mar 6, 2025
c0f51fe
Merge branch 'master' into feature/assemble-tx
netrome Mar 6, 2025
3c29542
Add more tests for the change and variable outputs
xgreenx Mar 6, 2025
dfd59ca
Handle cases with zero gas price and when we don't need base asset to…
xgreenx Mar 7, 2025
7a42126
Make audit happy
xgreenx Mar 7, 2025
a5fed62
Merge branch 'master' into feature/assemble-tx
xgreenx Mar 7, 2025
ca42157
Merge branch 'master' into feature/assemble-tx
rymnc Mar 7, 2025
1760da4
Fixed panic during adding change outputs.
xgreenx Mar 9, 2025
13e0607
Make CI happy
xgreenx Mar 9, 2025
4ce0dc9
Merge branch 'master' into feature/assemble-tx
xgreenx Mar 11, 2025
876241e
Merge branch 'master' into feature/assemble-tx
xgreenx Mar 11, 2025
14f842a
Merge branch 'master' into feature/assemble-tx
xgreenx Mar 11, 2025
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
24 changes: 24 additions & 0 deletions .changes/added/2769.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Added a new `assembleTx` GraphQL endpoint.
The endpoint can be used to assemble the transaction based on the provided requirements.

The returned transaction contains:
- Input coins to cover `required_balances`
- Input coins to cover the fee of the transaction based on the gas price from `block_horizon`
- `Change` or `Destroy` outputs for all assets from the inputs
- `Variable` outputs in the case they are required during the execution
- `Contract` inputs and outputs in the case they are required during the execution
- Reserved witness slots for signed coins filled with `64` zeroes
- Set script gas limit(unless `script` is empty)
- Estimated predicates, if `estimate_predicates == true`

Returns an error if:
- The number of required balances exceeds the maximum number of inputs allowed.
- The fee address index is out of bounds.
- The same asset has multiple change policies(either the receiver of
the change is different, or one of the policies states about the destruction
of the token while the other does not). The `Change` output from the transaction
also count as a `ChangePolicy`.
- The number of excluded coin IDs exceeds the maximum number of inputs allowed.
- Required assets have multiple entries.
- If accounts don't have sufficient amounts to cover the transaction requirements in assets.
- If a constructed transaction breaks the rules defined by consensus parameters.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion bin/e2e-test-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ license = { workspace = true }
repository = { workspace = true }
version = { workspace = true }
name = "fuel-core-e2e-client"
publish = true
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
Expand All @@ -24,6 +24,7 @@ itertools = { workspace = true }
libtest-mimic = "0.6.0"
serde = { workspace = true }
serde_json = { workspace = true }
test-helpers = { path = "../../tests/test-helpers" }
tikv-jemallocator = { workspace = true }
tokio = { workspace = true }
toml = { version = "0.5" }
Expand Down
125 changes: 29 additions & 96 deletions bin/e2e-test-client/src/test_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ use fuel_core_types::{
fuel_vm::SecretKey,
};
use itertools::Itertools;
use test_helpers::assemble_tx::{
AssembleAndRunTx,
SigningAccount,
};

use crate::config::{
ClientConfig,
Expand Down Expand Up @@ -121,42 +125,15 @@ impl Wallet {
asset_id: Option<AssetId>,
) -> anyhow::Result<Transaction> {
let asset_id = asset_id.unwrap_or(*self.consensus_params.base_asset_id());
let total_amount = transfer_amount + BASE_AMOUNT;
// select coins
let coins = &self
let tx = self
.client
.coins_to_spend(&self.address, vec![(asset_id, total_amount, None)], None)
.await?[0];

// build transaction
let mut tx = TransactionBuilder::script(Default::default(), Default::default());
tx.max_fee_limit(BASE_AMOUNT);
tx.script_gas_limit(0);

for coin in coins {
if let CoinType::Coin(coin) = coin {
tx.add_unsigned_coin_input(
self.secret,
coin.utxo_id,
coin.amount,
coin.asset_id,
Default::default(),
);
}
}
tx.add_output(Output::Coin {
to: destination,
amount: transfer_amount,
asset_id,
});
tx.add_output(Output::Change {
to: self.address,
amount: 0,
asset_id,
});
tx.with_params(self.consensus_params.clone());
.assemble_transfer(
SigningAccount::Wallet(self.secret),
vec![(destination, asset_id, transfer_amount)],
)
.await?;

Ok(tx.finalize_as_transaction())
Ok(tx)
}

/// Creates the script transaction that collects fee.
Expand All @@ -165,16 +142,6 @@ impl Wallet {
coinbase_contract: ContractId,
asset_id: AssetId,
) -> anyhow::Result<Transaction> {
// select coins
let coins = &self
.client
.coins_to_spend(
&self.address,
vec![(*self.consensus_params.base_asset_id(), BASE_AMOUNT, None)],
None,
)
.await?[0];

let output_index = 2u64;
let call_struct_register = 0x10;
// Now call the fee collection contract to withdraw the fees
Expand All @@ -189,59 +156,21 @@ impl Wallet {
op::call(call_struct_register, RegId::ZERO, RegId::ZERO, RegId::CGAS),
op::ret(RegId::ONE),
];
let script_data = asset_id
.to_bytes()
.into_iter()
.chain(output_index.to_bytes().into_iter())
.chain(coinbase_contract.to_bytes().into_iter())
.chain(0u64.to_bytes().into_iter())
.chain(0u64.to_bytes().into_iter())
.collect();

// build transaction
let mut tx_builder = TransactionBuilder::script(
script.into_iter().collect(),
asset_id
.to_bytes()
.into_iter()
.chain(output_index.to_bytes().into_iter())
.chain(coinbase_contract.to_bytes().into_iter())
.chain(0u64.to_bytes().into_iter())
.chain(0u64.to_bytes().into_iter())
.collect(),
);
tx_builder.max_fee_limit(BASE_AMOUNT);
tx_builder
.script_gas_limit(self.consensus_params.tx_params().max_gas_per_tx() / 10);

tx_builder.add_input(Input::contract(
Default::default(),
Default::default(),
Default::default(),
Default::default(),
coinbase_contract,
));
for coin in coins {
if let CoinType::Coin(coin) = coin {
tx_builder.add_unsigned_coin_input(
self.secret,
coin.utxo_id,
coin.amount,
coin.asset_id,
Default::default(),
);
}
}
tx_builder.add_output(Output::contract(
0,
Default::default(),
Default::default(),
));
tx_builder.add_output(Output::Change {
to: self.address,
amount: 0,
asset_id,
});
tx_builder.add_output(Output::Variable {
to: Default::default(),
amount: Default::default(),
asset_id: Default::default(),
});
tx_builder.with_params(self.consensus_params.clone());
let tx = self
.client
.assemble_script(script, script_data, SigningAccount::Wallet(self.secret))
.await?;

Ok(tx_builder.finalize_as_transaction())
Ok(tx)
}

/// Transfers coins from this wallet to another
Expand Down Expand Up @@ -280,7 +209,11 @@ impl Wallet {
// select coins
let coins = &self
.client
.coins_to_spend(&self.address, vec![(asset_id, total_amount, None)], None)
.coins_to_spend(
&self.address,
vec![(asset_id, u128::from(total_amount), None)],
None,
)
.await?[0];

let ContractConfig {
Expand Down
1 change: 1 addition & 0 deletions bin/fuel-core/src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,7 @@ impl Command {
coins_to_spend: graphql.costs.coins_to_spend,
get_peers: graphql.costs.get_peers,
estimate_predicates: graphql.costs.estimate_predicates,
assemble_tx: graphql.costs.assemble_tx,
dry_run: graphql.costs.dry_run,
storage_read_replay: graphql.costs.storage_read_replay,
submit: graphql.costs.submit,
Expand Down
8 changes: 8 additions & 0 deletions bin/fuel-core/src/cli/run/graphql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ pub struct QueryCosts {
)]
pub dry_run: usize,

/// Query costs for assembling the transaction.
#[clap(
long = "query-cost-assemble-tx",
default_value = DEFAULT_QUERY_COSTS.assemble_tx.to_string(),
env
)]
pub assemble_tx: usize,

/// Query costs for generating execution trace for a block.
#[clap(
long = "query-cost-storage-read-replay",
Expand Down
2 changes: 1 addition & 1 deletion crates/chain-config/src/config/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ mod writer;

// Fuel Network human-readable part for bech32 encoding
pub const FUEL_BECH32_HRP: &str = "fuel";
pub const TESTNET_INITIAL_BALANCE: u64 = 10_000_000;
pub const TESTNET_INITIAL_BALANCE: u64 = 10_000_000_000;

pub const TESTNET_WALLET_SECRETS: [&str; 5] = [
"0xde97d8624a438121b86a1956544bd72ed68cd69f2c99555b08b1e8c51ffd511c",
Expand Down
Loading
Loading