Skip to content

Commit

Permalink
Chain ID included in transaction ID's and predicate owners (#406)
Browse files Browse the repository at this point in the history
* use chain id for predicate root

* include chain id in tx id

* add consensus params to tx builder

* add chain id to gm

* merge master

* update rust to 1.67.1

* deal with merge conflicts

* fmt

* fix missing 'with_params'

* refactor tx calculation into common function

---------

Co-authored-by: Green Baneling <XgreenX9999@gmail.com>
  • Loading branch information
Voxelot and xgreenx authored Mar 28, 2023
1 parent d46da52 commit 8b007d1
Show file tree
Hide file tree
Showing 35 changed files with 326 additions and 161 deletions.
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

0 comments on commit 8b007d1

Please sign in to comment.