Skip to content

Commit

Permalink
Add GTF getters for tx bytes size and address (#692)
Browse files Browse the repository at this point in the history
* Add GTF getters for tx bytes size and address

* fmt

* Add changelog entry

* Move TxStart to GM

* Reassign TxLength

* fmt
  • Loading branch information
Dentosal authored Mar 8, 2024
1 parent 523f9df commit 610b968
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed

#### Breaking

- [#692](https://github.com/FuelLabs/fuel-vm/pull/692): Add GTF getters for tx size and address.

## [Version 0.47.1]

### Added
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 @@ -27,6 +27,9 @@ crate::enum_try_from! {

/// Get the Chain ID this VM is operating within
GetChainId = 0x04,

/// Get memory address where the transaction is located
TxStart = 0x05,
},
Immediate18
}
Expand Down Expand Up @@ -86,6 +89,9 @@ crate::enum_try_from! {
/// Set `$rA` to `Memory address of tx.witnesses[$rB]`
ScriptWitnessAtIndex = 0x00D,

/// Set `$rA` to size of the transaction in memory, in bytes
TxLength = 0x00E,

/// Set `$rA` to `tx.bytecodeLength`
CreateBytecodeLength = 0x100,

Expand Down
34 changes: 33 additions & 1 deletion fuel-vm/src/interpreter/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
context::Context,
convert,
error::SimpleResult,
interpreter::memory::read_bytes,
};

use fuel_asm::{
Expand Down Expand Up @@ -55,10 +56,19 @@ where
ra: RegisterId,
imm: Immediate18,
) -> SimpleResult<()> {
let tx_offset = self.tx_offset() as Word;
let chain_id = self.chain_id();
let (SystemRegisters { pc, .. }, mut w) = split_registers(&mut self.registers);
let result = &mut w[WriteRegKey::try_from(ra)?];
metadata(&self.context, &self.frames, pc, result, imm, chain_id)
metadata(
&self.context,
&self.frames,
pc,
result,
imm,
chain_id,
tx_offset,
)
}

pub(crate) fn get_transaction_field(
Expand All @@ -68,11 +78,21 @@ where
imm: Immediate12,
) -> SimpleResult<()> {
let tx_offset = self.tx_offset();
let tx_size = Word::from_be_bytes(
read_bytes(
&self.memory,
(tx_offset - 8) // Tx size is stored just below the tx bytes
.try_into()
.expect("tx offset impossibly large"),
)
.expect("Tx length not in memory"),
);
let (SystemRegisters { pc, .. }, mut w) = split_registers(&mut self.registers);
let result = &mut w[WriteRegKey::try_from(ra)?];
let input = GTFInput {
tx: &self.tx,
tx_offset,
tx_size,
pc,
};
input.get_transaction_field(result, b, imm)
Expand All @@ -86,6 +106,7 @@ pub(crate) fn metadata(
result: &mut Word,
imm: Immediate18,
chain_id: ChainId,
tx_offset: Word,
) -> SimpleResult<()> {
let external = context.is_external();
let args = GMArgs::try_from(imm)?;
Expand All @@ -103,6 +124,10 @@ pub(crate) fn metadata(
*result = chain_id.into();
}

GMArgs::TxStart => {
*result = tx_offset;
}

_ => return Err(PanicReason::ExpectedInternalContext.into()),
}
} else {
Expand All @@ -123,6 +148,11 @@ pub(crate) fn metadata(
GMArgs::GetChainId => {
*result = chain_id.into();
}

GMArgs::TxStart => {
*result = tx_offset;
}

_ => return Err(PanicReason::ExpectedInternalContext.into()),
}
}
Expand All @@ -134,6 +164,7 @@ pub(crate) fn metadata(
struct GTFInput<'vm, Tx> {
tx: &'vm Tx,
tx_offset: usize,
tx_size: Word,
pc: RegMut<'vm, PC>,
}

Expand Down Expand Up @@ -198,6 +229,7 @@ impl<Tx> GTFInput<'_, Tx> {
.witnesses_offset_at(b)
.ok_or(PanicReason::WitnessNotFound)?) as Word
}
GTFArgs::TxLength => self.tx_size,

// Input
GTFArgs::InputType => {
Expand Down
8 changes: 7 additions & 1 deletion fuel-vm/src/interpreter/metadata/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use alloc::vec;

use fuel_tx::Script;
use fuel_tx::{
Script,
TxParameters,
};
use fuel_types::BlockHeight;
use test_case::test_case;

Expand All @@ -22,6 +25,7 @@ fn test_metadata() {
&mut result,
imm,
ChainId::default(),
TxParameters::default().tx_offset() as Word,
)
.unwrap();
assert_eq!(pc, 8);
Expand All @@ -35,6 +39,7 @@ fn test_get_transaction_field() {
let input = GTFInput {
tx: &tx,
tx_offset: 0,
tx_size: fuel_tx::TxParameters::DEFAULT.tx_offset() as Word,
pc: RegMut::new(&mut pc),
};
let mut result = 1;
Expand Down Expand Up @@ -66,6 +71,7 @@ fn get_chain_id(context: Context, chain_id: u64) {
&mut result,
imm,
chain_id.into(),
TxParameters::default().tx_offset() as Word,
)
.unwrap();

Expand Down
39 changes: 39 additions & 0 deletions fuel-vm/src/tests/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,37 @@ fn get_metadata_chain_id() {
}
}

#[test]
fn get_metadata_tx_start() {
let gas_limit = 1_000_000;
let height = BlockHeight::default();
let mut storage = MemoryStorage::default();

let script = TransactionBuilder::script(
vec![op::gm_args(0x20, GMArgs::TxStart), op::ret(0x20)]
.into_iter()
.collect(),
vec![],
)
.script_gas_limit(gas_limit)
.add_random_fee_input()
.finalize()
.into_checked(height, &ConsensusParameters::default())
.unwrap();

let receipts = Transactor::<_, _>::new(&mut storage, InterpreterParams::default())
.transact(script)
.receipts()
.expect("Failed to transact")
.to_owned();

if let Receipt::Return { val, .. } = receipts[0].clone() {
assert_eq!(val, TxParameters::DEFAULT.tx_offset() as Word);
} else {
panic!("expected return receipt, instead of {:?}", receipts[0])
}
}

#[test]
fn get_transaction_fields() {
let rng = &mut StdRng::seed_from_u64(2322u64);
Expand Down Expand Up @@ -484,6 +515,14 @@ fn get_transaction_fields() {
op::eq(0x10, 0x10, 0x11),
op::and(0x20, 0x20, 0x10),

op::gtf_args(0x10, RegId::ZERO, GTFArgs::TxLength),
op::movi(0x11, 100), // Tx lenght is too complicated to backpatch
op::gt(0x10, 0x10, 0x11), // so just make sure it's over some arbitrary number
op::and(0x20, 0x20, 0x10),
op::movi(0x11, 10_000), // and
op::lt(0x10, 0x10, 0x11), // below some arbitrary number
op::and(0x20, 0x20, 0x10),

op::movi(0x11, tip as Immediate18),
op::movi(0x19, 0x00),
op::gtf_args(0x10, 0x19, GTFArgs::PolicyTip),
Expand Down

0 comments on commit 610b968

Please sign in to comment.