Skip to content

Commit

Permalink
Add TxPointer to input coin and contract (#170)
Browse files Browse the repository at this point in the history
  • Loading branch information
vlopes11 authored Aug 1, 2022
1 parent 6473312 commit be7de5a
Show file tree
Hide file tree
Showing 20 changed files with 745 additions and 156 deletions.
6 changes: 4 additions & 2 deletions fuel-tx/src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
CheckedTransaction, ConsensusParameters, Input, Output, StorageSlot, Transaction, Witness,
CheckedTransaction, ConsensusParameters, Input, Output, StorageSlot, Transaction, TxPointer,
Witness,
};

use fuel_crypto::SecretKey;
Expand Down Expand Up @@ -82,13 +83,14 @@ impl TransactionBuilder {
utxo_id: crate::UtxoId,
amount: Word,
asset_id: fuel_types::AssetId,
tx_pointer: TxPointer,
maturity: Word,
) -> &mut Self {
let pk = secret.public_key();

self.sign_keys.push(secret);
self.tx
.add_unsigned_coin_input(utxo_id, &pk, amount, asset_id, maturity);
.add_unsigned_coin_input(utxo_id, &pk, amount, asset_id, tx_pointer, maturity);

self
}
Expand Down
58 changes: 52 additions & 6 deletions fuel-tx/src/checked_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,24 @@ impl CheckedTransaction {
})
}

/// Prepare the transaction for VM initialization for script execution
///
/// The callback argument is to expect a contract id and return its balance root and state root
#[cfg(feature = "std")]
pub fn prepare_init_script<F>(&mut self, f: F) -> io::Result<&mut Self>
where
F: FnMut(&fuel_types::ContractId) -> io::Result<(Bytes32, Bytes32)>,
{
self.transaction.prepare_init_script(f)?;
Ok(self)
}

/// Prepare the transaction for VM initialization for predicate verification
pub fn prepare_init_predicate(&mut self) -> &mut Self {
self.transaction.prepare_init_predicate();
self
}

fn _initial_free_balances(
transaction: &Transaction,
params: &ConsensusParameters,
Expand Down Expand Up @@ -582,10 +600,17 @@ mod tests {
rng.gen(),
input_amount,
asset,
rng.gen(),
0,
0,
))
.add_input(Input::contract(rng.gen(), rng.gen(), rng.gen(), rng.gen()))
.add_input(Input::contract(
rng.gen(),
rng.gen(),
rng.gen(),
rng.gen(),
rng.gen(),
))
.add_output(Output::contract(1, rng.gen(), rng.gen()))
.add_output(Output::coin(rng.gen(), 10, asset))
.add_output(Output::change(rng.gen(), 0, asset))
Expand Down Expand Up @@ -694,10 +719,17 @@ mod tests {
.gas_price(1)
.gas_limit(100)
// base asset
.add_unsigned_coin_input(secret, rng.gen(), input_amount, AssetId::default(), 0)
.add_unsigned_coin_input(
secret,
rng.gen(),
input_amount,
AssetId::default(),
rng.gen(),
0,
)
.add_output(Output::change(rng.gen(), 0, AssetId::default()))
// arbitrary spending asset
.add_unsigned_coin_input(secret, rng.gen(), input_amount, any_asset, 0)
.add_unsigned_coin_input(secret, rng.gen(), input_amount, any_asset, rng.gen(), 0)
.add_output(Output::coin(rng.gen(), input_amount + 1, any_asset))
.add_output(Output::change(rng.gen(), 0, any_asset))
.finalize();
Expand Down Expand Up @@ -762,8 +794,14 @@ mod tests {
TransactionBuilder::script(vec![], vec![])
.gas_price(gas_price)
.gas_limit(gas_limit)
.add_unsigned_coin_input(rng.gen(), rng.gen(), input_amount, asset, 0)
.add_input(Input::contract(rng.gen(), rng.gen(), rng.gen(), rng.gen()))
.add_unsigned_coin_input(rng.gen(), rng.gen(), input_amount, asset, rng.gen(), 0)
.add_input(Input::contract(
rng.gen(),
rng.gen(),
rng.gen(),
rng.gen(),
rng.gen(),
))
.add_output(Output::contract(1, rng.gen(), rng.gen()))
.add_output(Output::coin(rng.gen(), output_amount, asset))
.add_output(Output::change(rng.gen(), 0, asset))
Expand All @@ -786,6 +824,7 @@ mod tests {
rng.gen(),
fee_input_amount,
asset,
rng.gen(),
0,
vec![],
vec![],
Expand Down Expand Up @@ -851,7 +890,14 @@ mod tests {
TransactionBuilder::script(vec![], vec![])
.gas_price(gas_price)
.gas_limit(gas_limit)
.add_unsigned_coin_input(rng.gen(), rng.gen(), input_amount, AssetId::default(), 0)
.add_unsigned_coin_input(
rng.gen(),
rng.gen(),
input_amount,
AssetId::default(),
rng.gen(),
0,
)
.add_output(Output::change(rng.gen(), 0, AssetId::default()))
.finalize()
}
Expand Down
24 changes: 12 additions & 12 deletions fuel-tx/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,6 @@ mod tests {
use rand::{rngs::StdRng, RngCore, SeedableRng};
use rstest::rstest;

macro_rules! set_snapshot_suffix {
($($expr:expr),*) => {{
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_suffix(format!($($expr,)*));
settings.bind_to_thread();
}}
}

// safe-guard against breaking changes to the code root calculation for valid
// sizes of bytecode (multiples of instruction size in bytes (half-word))
#[rstest]
Expand All @@ -168,8 +160,12 @@ mod tests {
let root = Contract::root_from_code(code);

// take root snapshot
set_snapshot_suffix!("instructions-{}", instructions);
insta::assert_debug_snapshot!(root);
insta::with_settings!(
{snapshot_suffix => format!("instructions-{}", instructions)},
{
insta::assert_debug_snapshot!(root);
}
);
}

// validate code_root is always equivalent to contract.root
Expand All @@ -193,8 +189,12 @@ mod tests {
let slots: Vec<StorageSlot> = state_slot_bytes.iter().map(Into::into).collect_vec();
let state_root = Contract::initial_state_root(&mut slots.iter());
// take root snapshot
set_snapshot_suffix!("state-root-{}", slots.len());
insta::assert_debug_snapshot!(state_root);
insta::with_settings!(
{snapshot_suffix => format!("state-root-{}", slots.len())},
{
insta::assert_debug_snapshot!(state_root);
}
);
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion fuel-tx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub use receipt::{Receipt, ScriptExecutionResult};
#[cfg(feature = "alloc")]
pub use transaction::{
ConsensusParameters, Input, InputRepr, Metadata, Output, OutputRepr, StorageSlot, Transaction,
TransactionFee, TransactionRepr, TxId, UtxoId, ValidationError, Witness,
TransactionFee, TransactionRepr, TxId, TxPointer, UtxoId, ValidationError, Witness,
};

#[cfg(feature = "alloc")]
Expand Down
57 changes: 49 additions & 8 deletions fuel-tx/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use fuel_types::{Address, AssetId, Bytes32, Salt, Word};
#[cfg(feature = "std")]
use fuel_crypto::{Message, SecretKey, Signature};

#[cfg(feature = "std")]
use std::io;

use alloc::vec::Vec;
use core::mem;

Expand All @@ -31,7 +34,7 @@ pub use consensus_parameters::ConsensusParameters;
pub use fee::TransactionFee;
pub use metadata::Metadata;
pub use repr::TransactionRepr;
pub use types::{Input, InputRepr, Output, OutputRepr, StorageSlot, UtxoId, Witness};
pub use types::{Input, InputRepr, Output, OutputRepr, StorageSlot, TxPointer, UtxoId, Witness};
pub use validation::ValidationError;

/// Identification of transaction (also called transaction hash)
Expand Down Expand Up @@ -327,12 +330,21 @@ impl Transaction {
owner: &PublicKey,
amount: Word,
asset_id: AssetId,
tx_pointer: TxPointer,
maturity: Word,
) {
let owner = Input::owner(owner);

let witness_index = self.witnesses().len() as u8;
let input = Input::coin_signed(utxo_id, owner, amount, asset_id, witness_index, maturity);
let input = Input::coin_signed(
utxo_id,
owner,
amount,
asset_id,
tx_pointer,
witness_index,
maturity,
);

self._add_witness(Witness::default());
self._add_input(input);
Expand Down Expand Up @@ -457,15 +469,44 @@ impl Transaction {
}
}

/// Prepare the transaction for VM initialization
///
/// # Steps
/// Prepare the transaction for VM initialization for script execution
///
/// 1) Zero all recipient and amount from message outputs
pub fn prepare_init(&mut self) -> &mut Self {
/// The callback argument is to expect a contract id and return its balance root and state root
#[cfg(feature = "std")]
pub fn prepare_init_script<F>(&mut self, mut f: F) -> io::Result<&mut Self>
where
F: FnMut(&fuel_types::ContractId) -> io::Result<(Bytes32, Bytes32)>,
{
let id = self.id();

let (inputs, outputs) = match self {
Transaction::Script {
inputs, outputs, ..
}
| Transaction::Create {
inputs, outputs, ..
} => (inputs, outputs),
};

inputs.iter_mut().for_each(|i| i.prepare_init_script(id));

outputs
.iter_mut()
.try_for_each(|o| o.prepare_init_script(inputs, &mut f))?;

Ok(self)
}

/// Prepare the transaction for VM initialization for predicate verification
pub fn prepare_init_predicate(&mut self) -> &mut Self {
self._inputs_mut()
.iter_mut()
.for_each(|i| i.prepare_init_predicate());

self._outputs_mut()
.iter_mut()
.for_each(|o| o.prepare_init());
.for_each(|o| o.prepare_init_predicate());

self
}

Expand Down
Loading

0 comments on commit be7de5a

Please sign in to comment.