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

Refactor make create contract helper function available outside of fuel core #2656

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .changes/changed/2656.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Migrate test helper function `create_contract` to `fuel_core_types::test_helpers::create_contract`, and refactor test in proof_system/global_merkle_root crate to use this function.
39 changes: 12 additions & 27 deletions crates/fuel-core/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ mod tests {
BlockHeight,
ChainId,
ContractId,
Salt,
Word,
},
fuel_vm::{
Expand Down Expand Up @@ -140,6 +139,7 @@ mod tests {
relayer::Event,
},
tai64::Tai64,
test_helpers::create_contract,
};
use fuel_core_upgradable_executor::executor::Executor;
use itertools::Itertools;
Expand Down Expand Up @@ -235,7 +235,8 @@ mod tests {
op::ret(RegId::ONE),
]
.into_iter()
.collect::<Vec<u8>>(),
.collect::<Vec<u8>>()
.as_slice(),
&mut rng,
);
let (script, data_offset) = script_with_data_offset!(
Expand Down Expand Up @@ -313,24 +314,6 @@ mod tests {
.into()
}

pub(crate) fn create_contract<R: Rng>(
contract_code: Vec<u8>,
rng: &mut R,
) -> (Create, ContractId) {
let salt: Salt = rng.gen();
let contract = Contract::from(contract_code.clone());
let root = contract.root();
let state_root = Contract::default_state_root();
let contract_id = contract.id(&salt, &root, &state_root);

let tx =
TransactionBuilder::create(contract_code.into(), salt, Default::default())
.add_fee_input()
.add_output(Output::contract_created(contract_id, state_root))
.finalize();
(tx, contract_id)
}

// Happy path test case that a produced block will also validate
#[test]
fn executor_validates_correctly_produced_block() {
Expand Down Expand Up @@ -1651,7 +1634,7 @@ mod tests {
// changes, the balance the root should be default - `[0; 32]`.
let mut rng = StdRng::seed_from_u64(2322u64);

let (create, contract_id) = create_contract(vec![], &mut rng);
let (create, contract_id) = create_contract(&[], &mut rng);
let non_modify_state_tx: Transaction = TxBuilder::new(2322)
.script_gas_limit(10000)
.coin_input(AssetId::zeroed(), 10000)
Expand Down Expand Up @@ -1707,7 +1690,7 @@ mod tests {
// it still should actualize them to use the balance and state roots before the execution.
let mut rng = StdRng::seed_from_u64(2322u64);

let (create, contract_id) = create_contract(vec![], &mut rng);
let (create, contract_id) = create_contract(&[], &mut rng);
// The transaction with invalid script.
let non_modify_state_tx: Transaction = TxBuilder::new(2322)
.start_script(vec![op::add(RegId::PC, RegId::PC, RegId::PC)], vec![])
Expand Down Expand Up @@ -1776,7 +1759,8 @@ mod tests {
op::ret(1),
]
.into_iter()
.collect::<Vec<u8>>(),
.collect::<Vec<u8>>()
.as_slice(),
&mut rng,
);

Expand Down Expand Up @@ -1880,7 +1864,8 @@ mod tests {
op::ret(1),
]
.into_iter()
.collect::<Vec<u8>>(),
.collect::<Vec<u8>>()
.as_slice(),
&mut rng,
);

Expand Down Expand Up @@ -1996,7 +1981,7 @@ mod tests {
// The foreign transfer of tokens should not affect the balance root of the transaction.
let mut rng = StdRng::seed_from_u64(2322u64);

let (create, contract_id) = create_contract(vec![], &mut rng);
let (create, contract_id) = create_contract(&[], &mut rng);

let transfer_amount = 100 as Word;
let asset_id = AssetId::from([2; 32]);
Expand Down Expand Up @@ -2127,7 +2112,7 @@ mod tests {
let mut rng = StdRng::seed_from_u64(2322);
// create a contract in block 1
// verify a block 2 with tx containing contract id from block 1, using the correct contract utxo_id from block 1.
let (tx, contract_id) = create_contract(vec![], &mut rng);
let (tx, contract_id) = create_contract(&[], &mut rng);
let first_block = PartialFuelBlock {
header: Default::default(),
transactions: vec![tx.into()],
Expand Down Expand Up @@ -2187,7 +2172,7 @@ mod tests {

// create a contract in block 1
// verify a block 2 containing contract id from block 1, with wrong input contract utxo_id
let (tx, contract_id) = create_contract(vec![], &mut rng);
let (tx, contract_id) = create_contract(&[], &mut rng);
let tx2: Transaction = TxBuilder::new(2322)
.start_script(vec![op::addi(0x10, RegId::ZERO, 0), op::ret(1)], vec![])
.contract_input(contract_id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,15 @@ use fuel_core_types::{
Address,
Bytes32,
ContractId,
Create,
Finalizable as _,
Output,
TransactionBuilder,
TxId,
TxPointer,
UtxoId,
},
fuel_types::BlockHeight,
fuel_vm::{
Contract,
Salt,
},
};

use rand::Rng;

// TODO: https://github.com/FuelLabs/fuel-core/issues/2654
// This code is copied from the executor. We should refactor it to be shared.
/// Create a contract create transaction
pub fn create_contract_tx(bytecode: &[u8], rng: &mut impl rand::RngCore) -> Create {
let salt: Salt = rng.gen();
let contract = Contract::from(bytecode);
let root = contract.root();
let state_root = Contract::default_state_root();
let contract_id = contract.id(&salt, &root, &state_root);

TransactionBuilder::create(bytecode.into(), salt, Default::default())
.add_fee_input()
.add_output(Output::contract_created(contract_id, state_root))
.finalize()
}

/// Sample a random UTxO ID
pub fn random_utxo_id(rng: &mut impl rand::RngCore) -> UtxoId {
let mut txid = TxId::default();
Expand Down
11 changes: 3 additions & 8 deletions crates/proof_system/global_merkle_root/storage/src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,14 +1077,8 @@ mod tests {
.collect::<Vec<u8>>();

let mut rng = StdRng::seed_from_u64(1337);
let create_contract_tx =
test_helpers::create_contract_tx(&contract_bytecode, &mut rng);
let contract_id = create_contract_tx
.metadata()
.as_ref()
.unwrap()
.body
.contract_id;
let (create_contract_tx, contract_id) =
fuel_core_types::test_helpers::create_contract(&contract_bytecode, &mut rng);

let mut storage: InMemoryStorage<Column> = InMemoryStorage::default();
let mut storage_tx = storage.write_transaction();
Expand All @@ -1097,6 +1091,7 @@ mod tests {
.unwrap();

storage_tx.commit().unwrap();

let stored_contract = storage
.read_transaction()
.storage_as_ref::<ContractsRawCode>()
Expand Down
4 changes: 4 additions & 0 deletions crates/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@ pub mod fuel_vm {
util,
};
}

/// Helpers for creating transactions in tests
#[cfg(feature = "test-helpers")]
pub mod test_helpers;
39 changes: 39 additions & 0 deletions crates/types/src/test_helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use crate::{
fuel_tx::{
ContractId,
Create,
Finalizable,
Output,
TransactionBuilder,
},
fuel_vm::{
Contract,
Salt,
},
};
use rand::Rng;

/// Helper function to create a contract creation transaction
/// from a given contract bytecode.
/// Example:
/// ```
/// let contract_bytecode = vec![];
/// let mut rng = rand::thread_rng();
/// let (tx, contract_id) = create_contract(&contract_bytecode, &mut rng);
/// ```
pub fn create_contract<R: Rng>(
contract_code: &[u8],
rng: &mut R,
) -> (Create, ContractId) {
let salt: Salt = rng.gen();
let contract = Contract::from(contract_code);
let root = contract.root();
let state_root = Contract::default_state_root();
let contract_id = contract.id(&salt, &root, &state_root);

let tx = TransactionBuilder::create(contract_code.into(), salt, Default::default())
.add_fee_input()
.add_output(Output::contract_created(contract_id, state_root))
.finalize();
(tx, contract_id)
}
Loading