Skip to content

Commit

Permalink
Extend support for getting the transaction script hash in std::tx (Fu…
Browse files Browse the repository at this point in the history
…elLabs#2781)

* Added function to get script hash

* Update sway-lib-std/src/tx.sw

Co-authored-by: Mohammad Fawaz <[email protected]>

* Update sway-lib-std/src/tx.sw

Co-authored-by: Braqzen <[email protected]>

* Review comment updates

* Updated to cleaner code style

Co-authored-by: Mohammad Fawaz <[email protected]>
Co-authored-by: Braqzen <[email protected]>
  • Loading branch information
3 people authored Sep 16, 2022
1 parent c8ce718 commit 6eb12bf
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 22 deletions.
51 changes: 31 additions & 20 deletions sway-lib-std/src/tx.sw
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
library tx;

use ::address::Address;
use ::constants::ZERO_B256;
use ::mem::read;
use ::option::Option;
use ::revert::revert;
Expand Down Expand Up @@ -69,8 +70,7 @@ pub fn tx_type() -> Transaction {
/// Get the transaction gas price for either tx type
/// (transaction-script or transaction-create).
pub fn tx_gas_price() -> u64 {
let type = tx_type();
match type {
match tx_type() {
Transaction::Script => {
__gtf::<u64>(0, GTF_SCRIPT_GAS_PRICE)
},
Expand All @@ -83,8 +83,7 @@ pub fn tx_gas_price() -> u64 {
/// Get the transaction-script gas limit for either tx type
/// (transaction-script or transaction-create).
pub fn tx_gas_limit() -> u64 {
let type = tx_type();
match type {
match tx_type() {
Transaction::Script => {
__gtf::<u64>(0, GTF_SCRIPT_GAS_LIMIT)
},
Expand All @@ -97,8 +96,7 @@ pub fn tx_gas_limit() -> u64 {
/// Get the transaction maturity for either tx type
/// (transaction-script or transaction-create).
pub fn tx_maturity() -> u32 {
let type = tx_type();
match type {
match tx_type() {
Transaction::Script => {
__gtf::<u32>(0, GTF_SCRIPT_MATURITY)
},
Expand All @@ -111,8 +109,7 @@ pub fn tx_maturity() -> u32 {
/// Get the transaction-script script length.
/// Reverts if not a transaction-script.
pub fn tx_script_length() -> u64 {
let type = tx_type();
match type {
match tx_type() {
Transaction::Script => {
__gtf::<u64>(0, GTF_SCRIPT_SCRIPT_LENGTH)
},
Expand All @@ -125,8 +122,7 @@ pub fn tx_script_length() -> u64 {
/// Get the transaction script data length.
/// Reverts if not a transaction-script.
pub fn tx_script_data_length() -> u64 {
let type = tx_type();
match type {
match tx_type() {
Transaction::Script => {
__gtf::<u64>(0, GTF_SCRIPT_SCRIPT_DATA_LENGTH)
},
Expand All @@ -139,8 +135,7 @@ pub fn tx_script_data_length() -> u64 {
/// Get the transaction witnesses count for either tx type
/// (transaction-script or transaction-create).
pub fn tx_witnesses_count() -> u64 {
let type = tx_type();
match type {
match tx_type() {
Transaction::Script => {
__gtf::<u64>(0, GTF_SCRIPT_WITNESSES_COUNT)
},
Expand All @@ -153,8 +148,7 @@ pub fn tx_witnesses_count() -> u64 {
// Get a pointer to the witness at index `index` for either tx type
/// (transaction-script or transaction-create).
pub fn tx_witness_pointer(index: u64) -> u64 {
let type = tx_type();
match type {
match tx_type() {
Transaction::Script => {
__gtf::<u64>(0, GTF_SCRIPT_WITNESS_AT_INDEX)
},
Expand All @@ -177,8 +171,7 @@ pub fn tx_witness_data<T>(index: u64) -> T {
/// Get the transaction receipts root.
/// Reverts if not a transaction-script.
pub fn tx_receipts_root() -> b256 {
let type = tx_type();
match type {
match tx_type() {
Transaction::Script => {
read::<b256>(__gtf::<u64>(0, GTF_SCRIPT_RECEIPTS_ROOT))
},
Expand All @@ -191,8 +184,7 @@ pub fn tx_receipts_root() -> b256 {
/// Get the transaction script start pointer.
/// Reverts if not a transaction-script.
pub fn tx_script_start_pointer() -> u64 {
let type = tx_type();
match type {
match tx_type() {
Transaction::Script => {
__gtf::<u64>(0, GTF_SCRIPT_SCRIPT)
},
Expand All @@ -206,8 +198,7 @@ pub fn tx_script_start_pointer() -> u64 {
/// Reverts if not a transaction-script
/// (transaction-create has no script data length),
pub fn tx_script_data_start_pointer() -> u64 {
let type = tx_type();
match type {
match tx_type() {
Transaction::Script => {
__gtf::<u64>(0, GTF_SCRIPT_SCRIPT_DATA)
},
Expand All @@ -232,6 +223,26 @@ pub fn tx_script_bytecode<T>() -> T {
read::<T>(tx_script_start_pointer())
}

/// Get the hash of the script bytecode.
/// Reverts if not a transaction-script
pub fn tx_script_bytecode_hash() -> b256 {
match tx_type() {
Transaction::Script => {
// Get the script memory details
let mut result_buffer = ZERO_B256;
let script_length = tx_script_length();
let script_ptr = tx_script_start_pointer();

// Run the hash opcode for the script in memory
asm(hash: result_buffer, ptr: script_ptr, len: script_length) {
s256 hash ptr len;
hash: b256
}
},
_ => revert(0),
}
}

const TX_ID_OFFSET = 0;

/// Get the id of the current transaction.
Expand Down
8 changes: 6 additions & 2 deletions test/src/sdk-harness/test_artifacts/tx_contract/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ contract;

use std::{
address::Address,
option::Option,
inputs::{
Input,
input_count,
input_owner,
input_pointer,
input_type,
},
option::Option,
outputs::{
Output,
output_count,
output_pointer,
output_type,
},
tx::*,
};
};

abi TxContractTest {
fn get_tx_type() -> Transaction;
Expand All @@ -31,6 +31,7 @@ abi TxContractTest {
fn get_tx_witnesses_count() -> u64;
fn get_tx_receipts_root() -> b256;
fn get_tx_script_start_pointer() -> u64;
fn get_tx_script_bytecode_hash() -> b256;

fn get_input_type(index: u64) -> Input;
fn get_tx_input_pointer(index: u64) -> u64;
Expand Down Expand Up @@ -75,6 +76,9 @@ impl TxContractTest for Contract {
fn get_tx_script_start_pointer() -> u64 {
tx_script_start_pointer()
}
fn get_tx_script_bytecode_hash() -> b256 {
tx_script_bytecode_hash()
}
fn get_tx_input_pointer(index: u64) -> u64 {
input_pointer(index)
}
Expand Down
29 changes: 29 additions & 0 deletions test/src/sdk-harness/test_projects/tx_fields/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use fuel_vm::fuel_crypto::Hasher;
use fuel_vm::fuel_tx::ConsensusParameters;
use fuel_vm::fuel_tx::Transaction as FuelTransaction;
use fuels::prelude::*;
use fuels::tx::{Bytes32, ContractId};
use std::str::FromStr;
Expand Down Expand Up @@ -170,6 +172,33 @@ async fn can_get_script_start_offset() {
assert_eq!(result.value, script_start_offset as u64);
}

#[tokio::test]
async fn can_get_script_bytecode_hash() {
let (contract_instance, _, _) = get_contracts().await;

let tx = contract_instance
.get_tx_script_bytecode_hash()
.get_call_execution_script()
.await
.unwrap()
.tx;
let hash = match tx {
FuelTransaction::Script { script, .. } => {
// Make sure script is actually something fairly substantial
assert!(script.len() > 1);
Hasher::hash(&script)
}
_ => Hasher::hash(&vec![]),
};

let result = contract_instance
.get_tx_script_bytecode_hash()
.call()
.await
.unwrap();
assert_eq!(result.value.to_vec(), hash.to_vec());
}

#[tokio::test]
async fn can_get_input_type() {
let (contract_instance, _, _) = get_contracts().await;
Expand Down

0 comments on commit 6eb12bf

Please sign in to comment.