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

Add GTF getters for tx bytes size and address #692

Merged
merged 6 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading