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

Chain ID included in transaction ID's and predicate owners #406

Merged
merged 14 commits into from
Mar 28, 2023
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ concurrency:

env:
CARGO_TERM_COLOR: always
RUST_VERSION: 1.67.0
RUST_VERSION: 1.67.1

jobs:
cargo:
Expand Down
6 changes: 6 additions & 0 deletions fuel-asm/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use fuel_types::{Immediate12, Immediate18};
const GM_IS_CALLER_EXTERNAL: u8 = 0x01;
const GM_GET_CALLER: u8 = 0x02;
const GM_GET_VERIFYING_PREDICATE: u8 = 0x03;
const GM_GET_CHAIN_ID: u8 = 0x04;

/// Argument list for GM (get metadata) instruction
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::EnumIter)]
Expand All @@ -22,6 +23,9 @@ pub enum GMArgs {

/// Get index of current predicate.
GetVerifyingPredicate = GM_GET_VERIFYING_PREDICATE,

/// Get the Chain ID this VM is operating within
GetChainId = GM_GET_CHAIN_ID,
}

impl TryFrom<Immediate18> for GMArgs {
Expand All @@ -32,6 +36,7 @@ impl TryFrom<Immediate18> for GMArgs {
GM_IS_CALLER_EXTERNAL => Ok(Self::IsCallerExternal),
GM_GET_CALLER => Ok(Self::GetCaller),
GM_GET_VERIFYING_PREDICATE => Ok(Self::GetVerifyingPredicate),
GM_GET_CHAIN_ID => Ok(Self::GetChainId),
_ => Err(PanicReason::InvalidMetadataIdentifier),
}
}
Expand Down Expand Up @@ -428,6 +433,7 @@ fn encode_gm_args() {
GMArgs::IsCallerExternal,
GMArgs::GetCaller,
GMArgs::GetVerifyingPredicate,
GMArgs::GetChainId,
];

args.into_iter().for_each(|a| {
Expand Down
22 changes: 17 additions & 5 deletions fuel-tx/src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::transaction::field::{BytecodeLength, BytecodeWitnessIndex, Witnesses};
use crate::transaction::{field, Chargeable, Create, Executable, Script};
use crate::{Cacheable, Input, Mint, Output, StorageSlot, Transaction, TxPointer, Witness};
use crate::{Cacheable, ConsensusParameters, Input, Mint, Output, StorageSlot, Transaction, TxPointer, Witness};

#[cfg(feature = "std")]
use crate::Signable;
Expand Down Expand Up @@ -88,6 +88,7 @@ pub struct TransactionBuilder<Tx> {

should_prepare_script: bool,
should_prepare_predicate: bool,
parameters: ConsensusParameters,

// We take the key by reference so this lib won't have the responsibility to properly zeroize
// the keys
Expand Down Expand Up @@ -165,8 +166,18 @@ impl<Tx> TransactionBuilder<Tx> {
should_prepare_script,
should_prepare_predicate,
sign_keys,
parameters: ConsensusParameters::DEFAULT,
}
}

pub fn get_params(&self) -> &ConsensusParameters {
&self.parameters
}

pub fn with_params(&mut self, parameters: ConsensusParameters) -> &mut Self {
self.parameters = parameters;
self
}
}

impl<Tx: Buildable> TransactionBuilder<Tx> {
Expand Down Expand Up @@ -264,6 +275,7 @@ impl<Tx: Buildable> TransactionBuilder<Tx> {

self
}

#[cfg(feature = "std")]
fn prepare_finalize(&mut self) {
if self.should_prepare_predicate {
Expand All @@ -281,9 +293,9 @@ impl<Tx: Buildable> TransactionBuilder<Tx> {

let mut tx = core::mem::take(&mut self.tx);

self.sign_keys.iter().for_each(|k| tx.sign_inputs(k));
self.sign_keys.iter().for_each(|k| tx.sign_inputs(k, &self.parameters));

tx.precompute();
tx.precompute(&self.parameters);

tx
}
Expand All @@ -294,7 +306,7 @@ impl<Tx: Buildable> TransactionBuilder<Tx> {

let mut tx = core::mem::take(&mut self.tx);

tx.precompute();
tx.precompute(&self.parameters);

tx
}
Expand All @@ -317,7 +329,7 @@ pub trait Finalizable<Tx> {
impl Finalizable<Mint> for TransactionBuilder<Mint> {
fn finalize(&mut self) -> Mint {
let mut tx = core::mem::take(&mut self.tx);
tx.precompute();
tx.precompute(&self.parameters);
tx
}

Expand Down
4 changes: 2 additions & 2 deletions fuel-tx/src/tests/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ fn create_input_data_offset() {
);

let mut tx_p = tx.clone();
tx_p.precompute();
tx_p.precompute(&ConsensusParameters::DEFAULT);

buffer.iter_mut().for_each(|b| *b = 0x00);
let _ = tx.read(buffer.as_mut_slice()).expect("Failed to serialize input");
Expand Down Expand Up @@ -826,7 +826,7 @@ fn script_input_coin_data_offset() {
);

let mut tx_p = tx.clone();
tx_p.precompute();
tx_p.precompute(&ConsensusParameters::DEFAULT);

buffer.iter_mut().for_each(|b| *b = 0x00);

Expand Down
2 changes: 1 addition & 1 deletion fuel-tx/src/tests/offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ fn iow_offset() {
let bytes = tx.to_bytes();

let mut tx_p = tx.clone();
tx_p.precompute();
tx_p.precompute(&ConsensusParameters::DEFAULT);

tx.inputs().iter().enumerate().for_each(|(x, i)| {
let offset = tx.inputs_offset_at(x).unwrap();
Expand Down
19 changes: 10 additions & 9 deletions fuel-tx/src/tests/valid_cases/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn input_coin_message_signature() {
let rng = &mut StdRng::seed_from_u64(8586);

fn check_inputs<Tx: Buildable>(tx: Tx) -> Result<(), CheckError> {
let txhash = tx.id();
let txhash = tx.id(&ConsensusParameters::DEFAULT);
let outputs = tx.outputs();
let witnesses = tx.witnesses();

Expand Down Expand Up @@ -42,8 +42,9 @@ fn input_coin_message_signature() {

f(&mut tx, &public);

tx.sign_inputs(&secret);
keys.iter().for_each(|sk| tx.sign_inputs(sk));
tx.sign_inputs(&secret, &ConsensusParameters::DEFAULT);
keys.iter()
.for_each(|sk| tx.sign_inputs(sk, &ConsensusParameters::DEFAULT));

check_inputs(tx)
}
Expand Down Expand Up @@ -108,7 +109,7 @@ fn coin_predicate() {
let txhash: Bytes32 = rng.gen();

let predicate = generate_nonempty_padded_bytes(rng);
let owner = (*Contract::root_from_code(&predicate)).into();
let owner = Input::predicate_owner(&predicate, &ConsensusParameters::DEFAULT);

Input::coin_predicate(
rng.gen(),
Expand All @@ -124,7 +125,7 @@ fn coin_predicate() {
.unwrap();

let predicate = vec![];
let owner = (*Contract::root_from_code(&predicate)).into();
let owner = Input::predicate_owner(&predicate, &ConsensusParameters::DEFAULT);

let err = Input::coin_predicate(
rng.gen(),
Expand Down Expand Up @@ -220,7 +221,7 @@ fn message_metadata() {
let txhash: Bytes32 = rng.gen();

let predicate = generate_nonempty_padded_bytes(rng);
let recipient = (*Contract::root_from_code(&predicate)).into();
let recipient = Input::predicate_owner(&predicate, &ConsensusParameters::DEFAULT);

Input::message_data_predicate(
rng.gen(),
Expand Down Expand Up @@ -248,7 +249,7 @@ fn message_metadata() {
assert_eq!(CheckError::InputWitnessIndexBounds { index: 0 }, err,);

let mut predicate = generate_nonempty_padded_bytes(rng);
let recipient = (*Contract::root_from_code(&predicate)).into();
let recipient = Input::predicate_owner(&predicate, &ConsensusParameters::DEFAULT);
predicate[0] = predicate[0].wrapping_add(1);

let err = Input::message_data_predicate(
Expand Down Expand Up @@ -327,7 +328,7 @@ fn message_message_coin() {
let txhash: Bytes32 = rng.gen();

let predicate = generate_nonempty_padded_bytes(rng);
let recipient = (*Contract::root_from_code(&predicate)).into();
let recipient = Input::predicate_owner(&predicate, &ConsensusParameters::DEFAULT);

Input::message_coin_predicate(
rng.gen(),
Expand All @@ -353,7 +354,7 @@ fn message_message_coin() {
assert_eq!(CheckError::InputWitnessIndexBounds { index: 0 }, err,);

let mut predicate = generate_nonempty_padded_bytes(rng);
let recipient = (*Contract::root_from_code(&predicate)).into();
let recipient = Input::predicate_owner(&predicate, &ConsensusParameters::DEFAULT);
predicate[0] = predicate[0].wrapping_add(1);

let err = Input::message_coin_predicate(
Expand Down
22 changes: 13 additions & 9 deletions fuel-tx/src/tests/valid_cases/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,9 +743,9 @@ fn tx_id_bytecode_len() {
vec![w_c],
);

let id_a = tx_a.id();
let id_b = tx_b.id();
let id_c = tx_c.id();
let id_a = tx_a.id(&PARAMS);
let id_b = tx_b.id(&PARAMS);
let id_c = tx_c.id(&PARAMS);

// bytecode with different length should produce different id
assert_ne!(id_a, id_b);
Expand All @@ -771,7 +771,7 @@ mod inputs {

let predicate = (0..1000).map(|_| rng.gen()).collect_vec();
// The predicate is an owner of the coin
let owner: Address = (*Contract::root_from_code(&predicate)).into();
let owner: Address = Input::predicate_owner(&predicate, &ConsensusParameters::DEFAULT);

let tx = TransactionBuilder::create(generate_bytes(rng).into(), rng.gen(), vec![])
.gas_limit(PARAMS.max_gas_per_tx)
Expand All @@ -787,9 +787,10 @@ mod inputs {
predicate,
vec![],
))
.with_params(PARAMS)
.finalize();

assert!(tx.check_predicate_owners());
assert!(tx.check_predicate_owners(&ConsensusParameters::DEFAULT));
}

#[test]
Expand All @@ -812,9 +813,10 @@ mod inputs {
predicate,
vec![],
))
.with_params(PARAMS)
.finalize();

assert!(!tx.check_predicate_owners());
assert!(!tx.check_predicate_owners(&ConsensusParameters::DEFAULT));
}

#[test]
Expand All @@ -823,7 +825,7 @@ mod inputs {

let predicate = (0..1000).map(|_| rng.gen()).collect_vec();
// The predicate is an recipient(owner) of the message
let recipient: Address = (*Contract::root_from_code(&predicate)).into();
let recipient: Address = Input::predicate_owner(&predicate, &ConsensusParameters::DEFAULT);

let tx = TransactionBuilder::create(generate_bytes(rng).into(), rng.gen(), vec![])
.gas_limit(PARAMS.max_gas_per_tx)
Expand All @@ -838,9 +840,10 @@ mod inputs {
predicate,
vec![],
))
.with_params(PARAMS)
.finalize();

assert!(tx.check_predicate_owners());
assert!(tx.check_predicate_owners(&ConsensusParameters::DEFAULT));
}

#[test]
Expand All @@ -862,8 +865,9 @@ mod inputs {
predicate,
vec![],
))
.with_params(PARAMS)
.finalize();

assert!(!tx.check_predicate_owners());
assert!(!tx.check_predicate_owners(&ConsensusParameters::DEFAULT));
}
}
4 changes: 2 additions & 2 deletions fuel-tx/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ pub trait Executable: field::Inputs + field::Outputs + field::Witnesses {

/// Checks that all owners of inputs in the predicates are valid.
#[cfg(feature = "std")]
fn check_predicate_owners(&self) -> bool {
fn check_predicate_owners(&self, parameters: &ConsensusParameters) -> bool {
self.inputs()
.iter()
.filter_map(|i| match i {
Expand All @@ -265,7 +265,7 @@ pub trait Executable: field::Inputs + field::Outputs + field::Witnesses {
_ => None,
})
.fold(true, |result, (owner, predicate)| {
result && Input::is_predicate_owner_valid(owner, predicate)
result && Input::is_predicate_owner_valid(owner, predicate, parameters)
})
}

Expand Down
Loading