Skip to content

Commit

Permalink
Add GM for base asset ID (#700)
Browse files Browse the repository at this point in the history
* Refactor fn metadata

* Add GM_BASE_ASSET_ID

* Add changelog entry

* Clippy

* Fix typo bsae->base

* Refactor fn metadata to use correct panics

* Add a test case
  • Loading branch information
Dentosal authored Mar 25, 2024
1 parent 88158d5 commit bb93537
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 56 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
affected types.
- [#588](https://github.com/FuelLabs/fuel-vm/pull/588): Re-worked the size calculation of the canonical
serialization/deserialization.
- [#700](https://github.com/FuelLabs/fuel-vm/pull/700): Add `BASE_ASSET_ID` to `GM` instruction.


#### Removed

Expand Down
5 changes: 5 additions & 0 deletions fuel-asm/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ crate::enum_try_from! {

/// Get memory address where the transaction is located
TxStart = 0x05,

/// Get memory address of base asset ID
BaseAssetId = 0x06,
},
Immediate18
}
Expand Down Expand Up @@ -268,6 +271,8 @@ fn encode_gm_args() {
GMArgs::GetCaller,
GMArgs::GetVerifyingPredicate,
GMArgs::GetChainId,
GMArgs::TxStart,
GMArgs::BaseAssetId,
];

args.into_iter().for_each(|a| {
Expand Down
3 changes: 3 additions & 0 deletions fuel-asm/src/panic_reason.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ enum_from! {
/// Attempt to use sequential memory instructions with too large slot count,
/// typically because it cannot fit into usize
TooManySlots = 0x2d,
/// Caller of this internal context is also expected to be internal,
/// i.e. $fp->$fp must be non-zero.
ExpectedNestedCaller = 0x2e,
}
}

Expand Down
7 changes: 4 additions & 3 deletions fuel-tx/src/transaction/consensus_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,9 +389,10 @@ impl TxParameters {
/// Transaction memory offset in VM runtime
pub const fn tx_offset(&self) -> usize {
Bytes32::LEN // Tx ID
+ WORD_SIZE // Tx size
// Asset ID/Balance coin input pairs
+ self.max_inputs as usize * (AssetId::LEN + WORD_SIZE)
+ AssetId::LEN // Base asset ID
// Asset ID/Balance coin input pairs
+ self.max_inputs as usize * (AssetId::LEN + WORD_SIZE)
+ WORD_SIZE // Tx size
}

/// Replace the max inputs with the given argument
Expand Down
7 changes: 6 additions & 1 deletion fuel-vm/src/consts.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! VM parameters

use fuel_types::{
AssetId,
Bytes32,
Word,
};
Expand Down Expand Up @@ -41,7 +42,11 @@ static_assertions::const_assert!(VM_MAX_RAM < usize::MAX as u64);
// no limits to heap for now.

/// Offset for the assets balances in VM memory
pub const VM_MEMORY_BALANCES_OFFSET: usize = Bytes32::LEN;
pub const VM_MEMORY_BASE_ASSET_ID_OFFSET: usize = Bytes32::LEN;

/// Offset for the assets balances in VM memory
pub const VM_MEMORY_BALANCES_OFFSET: usize =
VM_MEMORY_BASE_ASSET_ID_OFFSET + AssetId::LEN;

/// Encoded len of a register id in an instruction (unused)
pub const VM_REGISTER_WIDTH: u8 = 6;
Expand Down
3 changes: 3 additions & 0 deletions fuel-vm/src/interpreter/initialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ where

self.push_stack(self.transaction().id(&self.chain_id()).as_ref())?;

let base_asset_id = self.interpreter_params.base_asset_id;
self.push_stack(&*base_asset_id)?;

runtime_balances.to_vm(self);

let tx_size = self.transaction().size() as Word;
Expand Down
69 changes: 22 additions & 47 deletions fuel-vm/src/interpreter/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,54 +108,29 @@ pub(crate) fn metadata(
chain_id: ChainId,
tx_offset: Word,
) -> SimpleResult<()> {
let external = context.is_external();
let args = GMArgs::try_from(imm)?;
let parent = context
.is_internal()
.then(|| frames.last().map(|f| f.registers()[RegId::FP]))
.flatten();

if external {
match args {
GMArgs::GetVerifyingPredicate => {
*result = context
.predicate()
.map(|p| p.idx() as Word)
.ok_or(PanicReason::TransactionValidity)?;
}

GMArgs::GetChainId => {
*result = chain_id.into();
}

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

_ => return Err(PanicReason::ExpectedInternalContext.into()),
}
} else {
let parent = frames
.last()
.map(|f| f.registers()[RegId::FP])
.expect("External context will always have a frame");

match args {
GMArgs::IsCallerExternal => {
*result = (parent == 0) as Word;
}

GMArgs::GetCaller if parent != 0 => {
*result = parent;
}

GMArgs::GetChainId => {
*result = chain_id.into();
}

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

_ => return Err(PanicReason::ExpectedInternalContext.into()),
}
}
*result = match GMArgs::try_from(imm)? {
GMArgs::GetVerifyingPredicate => context
.predicate()
.map(|p| p.idx() as Word)
.ok_or(PanicReason::TransactionValidity)?,
GMArgs::GetChainId => chain_id.into(),
GMArgs::BaseAssetId => VM_MEMORY_BASE_ASSET_ID_OFFSET as Word,
GMArgs::TxStart => tx_offset,
GMArgs::GetCaller => match parent {
Some(0) => return Err(PanicReason::ExpectedNestedCaller.into()),
Some(parent) => parent,
None => return Err(PanicReason::ExpectedInternalContext.into()),
},
GMArgs::IsCallerExternal => match parent {
Some(p) => (p == 0) as Word,
None => return Err(PanicReason::ExpectedInternalContext.into()),
},
};

inc_pc(pc)?;
Ok(())
Expand Down
45 changes: 45 additions & 0 deletions fuel-vm/src/tests/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,51 @@ fn get_metadata_chain_id() {
}
}

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

let mut params = ConsensusParameters::standard();
params.set_base_asset_id(AssetId::from([5; 32]));

let script = TransactionBuilder::script(
vec![
op::gm_args(0x20, GMArgs::BaseAssetId),
op::movi(0x21, AssetId::LEN.try_into().unwrap()),
op::logd(RegId::ZERO, RegId::ZERO, 0x20, 0x21),
op::ret(RegId::ONE),
]
.into_iter()
.collect(),
vec![],
)
.script_gas_limit(gas_limit)
.add_random_fee_input()
.finalize()
.into_checked(height, &params)
.unwrap();

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

if let Receipt::LogData { data, .. } = receipts[0].clone() {
assert_eq!(data.unwrap(), params.base_asset_id().to_bytes());
} else {
panic!("expected LogData receipt, instead of {:?}", receipts[0]);
}
}

#[test]
fn get_metadata_tx_start() {
let gas_limit = 1_000_000;
Expand Down
7 changes: 2 additions & 5 deletions fuel-vm/src/tests/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ use rand::{
#[cfg(feature = "alloc")]
use alloc::vec;

use crate::consts::WORD_SIZE;

#[test]
fn transaction_can_be_executed_after_maturity() {
const MATURITY: BlockHeight = BlockHeight::new(1);
Expand Down Expand Up @@ -62,9 +60,8 @@ fn malleable_fields_do_not_affect_validity() {

let params = ConsensusParameters::default();

let tx_size_ptr =
32 + (params.tx_params().max_inputs as usize * (AssetId::LEN + WORD_SIZE));
let tx_start_ptr = tx_size_ptr + 8;
let tx_start_ptr = params.tx_params().tx_offset();
let tx_size_ptr = tx_start_ptr - 8;

let tx = TransactionBuilder::script(
vec![
Expand Down

0 comments on commit bb93537

Please sign in to comment.