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 consensus params to the vm for tx validation #130

Merged
merged 1 commit into from
May 25, 2022
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
3 changes: 2 additions & 1 deletion src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::context::Context;
use crate::state::Debugger;
use std::collections::HashMap;

use fuel_tx::{Receipt, Transaction};
use fuel_tx::{ConsensusParameters, Receipt, Transaction};
use fuel_types::{AssetId, Word};

mod alu;
Expand Down Expand Up @@ -58,6 +58,7 @@ pub struct Interpreter<S> {
profiler: Profiler,
// track the offset for each unused balance in memory
unused_balance_index: HashMap<AssetId, usize>,
consensus_parameters: ConsensusParameters,
}

impl<S> Interpreter<S> {
Expand Down
7 changes: 4 additions & 3 deletions src/interpreter/constructors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Exposed constructors API for the [`Interpreter`]

use fuel_tx::Transaction;
use fuel_tx::{ConsensusParameters, Transaction};

use super::Interpreter;
use crate::consts::*;
Expand All @@ -17,7 +17,7 @@ impl<S> Interpreter<S> {
/// If the provided storage implements
/// [`crate::storage::InterpreterStorage`], the returned interpreter
/// will provide full functionality.
pub fn with_storage(storage: S) -> Self {
pub fn with_storage(storage: S, params: ConsensusParameters) -> Self {
Self {
registers: [0; VM_REGISTER_COUNT],
memory: vec![0; VM_MAX_RAM as usize],
Expand All @@ -31,6 +31,7 @@ impl<S> Interpreter<S> {
#[cfg(feature = "profile-any")]
profiler: Profiler::default(),
unused_balance_index: Default::default(),
consensus_parameters: params,
}
}

Expand All @@ -47,7 +48,7 @@ where
S: Default,
{
fn default() -> Self {
Self::with_storage(Default::default())
Self::with_storage(Default::default(), Default::default())
}
}

Expand Down
22 changes: 14 additions & 8 deletions src/interpreter/executors/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::state::{ExecuteState, ProgramState, StateTransitionRef};
use crate::storage::InterpreterStorage;

use fuel_asm::PanicReason;
use fuel_tx::{Contract, Input, Output, Receipt, ScriptExecutionResult, Transaction};
use fuel_tx::{ConsensusParameters, Contract, Input, Output, Receipt, ScriptExecutionResult, Transaction};
use fuel_types::{bytes::SerializableVec, Word};

impl<S> Interpreter<S>
Expand All @@ -25,8 +25,8 @@ where
///
/// This is not a valid entrypoint for debug calls. It will only return a `bool`, and not the
/// VM state required to trace the execution steps.
pub fn check_predicates(tx: Transaction) -> bool {
let mut vm = Interpreter::with_storage(S::default());
pub fn check_predicates(tx: Transaction, params: ConsensusParameters) -> bool {
let mut vm = Interpreter::with_storage(S::default(), params);

if !tx.check_predicate_owners() {
return false;
Expand Down Expand Up @@ -63,7 +63,7 @@ where
fn init_predicate(&mut self, tx: Transaction) -> bool {
let block_height = 0;

self.init(true, block_height, tx).is_ok()
self.init(true, block_height, tx, self.consensus_parameters).is_ok()
}

fn input_to_predicate(tx: &Transaction, idx: usize) -> Option<MemoryRange> {
Expand Down Expand Up @@ -132,7 +132,7 @@ where
// Verify predicates
// https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/tx_validity.md#predicate-verification
// TODO implement debug support
if !Interpreter::<()>::check_predicates(self.tx.clone()) {
if !Interpreter::<()>::check_predicates(self.tx.clone(), self.consensus_parameters) {
return Err(InterpreterError::PredicateFailure);
}

Expand Down Expand Up @@ -286,8 +286,12 @@ where
/// Allocate internally a new instance of [`Interpreter`] with the provided
/// storage, initialize it with the provided transaction and return the
/// result of th execution in form of [`StateTransition`]
pub fn transact_owned(storage: S, tx: Transaction) -> Result<StateTransition, InterpreterError> {
Interpreter::with_storage(storage)
pub fn transact_owned(
storage: S,
tx: Transaction,
params: ConsensusParameters,
) -> Result<StateTransition, InterpreterError> {
Interpreter::with_storage(storage, params)
.transact(tx)
.map(|st| st.into_owned())
}
Expand All @@ -297,7 +301,9 @@ where
/// of the interpreter and will avoid unnecessary copy with the data
/// that can be referenced from the interpreter instance itself.
pub fn transact(&mut self, tx: Transaction) -> Result<StateTransitionRef<'_>, InterpreterError> {
let state_result = self.init_with_storage(tx).and_then(|_| self.run());
let state_result = self
.init_with_storage(tx, self.consensus_parameters)
.and_then(|_| self.run());

#[cfg(feature = "profile-any")]
self.profiler.on_transaction(&state_result);
Expand Down
14 changes: 9 additions & 5 deletions src/interpreter/initialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ use std::io;

impl<S> Interpreter<S> {
/// Initialize the VM with a given transaction
pub fn init(&mut self, predicate: bool, block_height: u32, mut tx: Transaction) -> Result<(), InterpreterError> {
let params = ConsensusParameters::default();

pub fn init(
&mut self,
predicate: bool,
block_height: u32,
mut tx: Transaction,
params: ConsensusParameters,
) -> Result<(), InterpreterError> {
tx.validate_without_signature(self.block_height() as Word, &params)?;
tx.precompute_metadata();

Expand Down Expand Up @@ -162,10 +166,10 @@ where
/// execution of contract opcodes.
///
/// For predicate verification, check [`Self::init`]
pub fn init_with_storage(&mut self, tx: Transaction) -> Result<(), InterpreterError> {
pub fn init_with_storage(&mut self, tx: Transaction, params: ConsensusParameters) -> Result<(), InterpreterError> {
let predicate = false;
let block_height = self.storage.block_height().map_err(InterpreterError::from_io)?;

self.init(predicate, block_height, tx)
self.init(predicate, block_height, tx, params)
}
}
6 changes: 4 additions & 2 deletions src/interpreter/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ mod tests {
vec![vec![].into()],
);

vm.init_with_storage(tx).expect("Failed to init VM!");
vm.init_with_storage(tx, Default::default())
.expect("Failed to init VM!");

for (asset_id, amount) in balances {
assert!(vm.external_asset_id_balance_sub(&asset_id, amount + 1).is_err());
Expand Down Expand Up @@ -293,7 +294,8 @@ mod tests {
vec![Witness::default()],
);

vm.init_with_storage(tx).expect("Failed to init VM!");
vm.init_with_storage(tx, Default::default())
.expect("Failed to init VM!");

// increase variable output
vm.set_variable_output(0, asset_id_to_update, amount_to_set, owner)
Expand Down
9 changes: 6 additions & 3 deletions src/interpreter/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,8 @@ mod tests {
fn memcopy() {
let mut vm = Interpreter::with_memory_storage();

vm.init_with_storage(Transaction::default()).expect("Failed to init VM");
vm.init_with_storage(Transaction::default(), Default::default())
.expect("Failed to init VM");

let alloc = 1024;

Expand Down Expand Up @@ -505,7 +506,8 @@ mod tests {
assert_eq!(m, m_p);

let mut vm = Interpreter::with_memory_storage();
vm.init_with_storage(Transaction::default()).expect("Failed to init VM");
vm.init_with_storage(Transaction::default(), Default::default())
.expect("Failed to init VM");

let bytes = 1024;
vm.instruction(
Expand Down Expand Up @@ -536,7 +538,8 @@ mod tests {
fn stack_alloc_ownership() {
let mut vm = Interpreter::with_memory_storage();

vm.init_with_storage(Transaction::default()).expect("Failed to init VM");
vm.init_with_storage(Transaction::default(), Default::default())
.expect("Failed to init VM");

vm.instruction(Interpreter::instruction_script, Opcode::MOVE(0x10, REG_SP).into())
.unwrap();
Expand Down
8 changes: 4 additions & 4 deletions src/memory_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::backtrace::Backtrace;
use crate::transactor::Transactor;

use fuel_tx::{Receipt, Transaction};
use fuel_tx::{ConsensusParameters, Receipt, Transaction};

mod storage;

Expand All @@ -29,9 +29,9 @@ impl<'a> AsMut<MemoryStorage> for MemoryClient<'a> {

impl<'a> MemoryClient<'a> {
/// Create a new instance of the memory client out of a provided storage.
pub fn new(storage: MemoryStorage) -> Self {
pub fn new(storage: MemoryStorage, params: ConsensusParameters) -> Self {
Self {
transactor: Transactor::new(storage),
transactor: Transactor::new(storage, params),
}
}

Expand Down Expand Up @@ -87,7 +87,7 @@ impl<'a> MemoryClient<'a> {

impl<'a> From<MemoryStorage> for MemoryClient<'a> {
fn from(s: MemoryStorage) -> Self {
Self::new(s)
Self::new(s, Default::default())
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/transactor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::interpreter::Interpreter;
use crate::state::StateTransitionRef;
use crate::storage::InterpreterStorage;

use fuel_tx::{Receipt, Transaction};
use fuel_tx::{ConsensusParameters, Receipt, Transaction};

use std::{mem, slice};

Expand All @@ -26,8 +26,8 @@ pub struct Transactor<'a, S> {

impl<'a, S> Transactor<'a, S> {
/// Transactor constructor
pub fn new(storage: S) -> Self {
Interpreter::with_storage(storage).into()
pub fn new(storage: S, params: ConsensusParameters) -> Self {
Interpreter::with_storage(storage, params).into()
}

/// State transition representation after the execution of a transaction.
Expand Down Expand Up @@ -185,6 +185,6 @@ where
S: Default,
{
fn default() -> Self {
Self::new(Default::default())
Self::new(Default::default(), Default::default())
}
}
2 changes: 1 addition & 1 deletion src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ pub mod test_helpers {
}

fn execute_tx(&mut self, tx: Transaction) -> StateTransition {
let mut client = MemoryClient::new(self.storage.clone());
let mut client = MemoryClient::new(self.storage.clone(), Default::default());
client.transact(tx);
let storage = client.as_ref().clone();
let txtor: Transactor<_> = client.into();
Expand Down
12 changes: 6 additions & 6 deletions tests/alu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn alu(registers_init: &[(RegisterId, Immediate18)], op: Opcode, reg: RegisterId
vec![],
);

let receipts = Transactor::new(storage)
let receipts = Transactor::new(storage, Default::default())
.transact(tx)
.receipts()
.expect("Failed to execute ALU script!")
Expand Down Expand Up @@ -65,7 +65,7 @@ fn alu_overflow(program: &[Opcode], reg: RegisterId, expected: u128, boolean: bo
vec![],
);

let receipts = Transactor::new(storage.clone())
let receipts = Transactor::new(storage.clone(), Default::default())
.transact(tx)
.receipts()
.expect("Failed to execute ALU script!")
Expand Down Expand Up @@ -101,7 +101,7 @@ fn alu_overflow(program: &[Opcode], reg: RegisterId, expected: u128, boolean: bo
vec![],
);

let receipts = Transactor::new(storage)
let receipts = Transactor::new(storage, Default::default())
.transact(tx)
.receipts()
.expect("Failed to execute ALU script!")
Expand Down Expand Up @@ -146,7 +146,7 @@ fn alu_err(registers_init: &[(RegisterId, Immediate18)], op: Opcode, reg: Regist
vec![],
);

let receipts = Transactor::new(storage.clone())
let receipts = Transactor::new(storage.clone(), Default::default())
.transact(tx)
.receipts()
.expect("Failed to execute ALU script!")
Expand Down Expand Up @@ -182,7 +182,7 @@ fn alu_err(registers_init: &[(RegisterId, Immediate18)], op: Opcode, reg: Regist
vec![],
);

let receipts = Transactor::new(storage)
let receipts = Transactor::new(storage, Default::default())
.transact(tx)
.receipts()
.expect("Failed to execute ALU script!")
Expand Down Expand Up @@ -219,7 +219,7 @@ fn alu_reserved(registers_init: &[(RegisterId, Immediate18)], op: Opcode) {
vec![],
vec![],
);
let receipts = Transactor::new(storage)
let receipts = Transactor::new(storage, Default::default())
.transact(tx)
.receipts()
.expect("Failed to execute ALU script!")
Expand Down
6 changes: 3 additions & 3 deletions tests/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ fn ecrecover() {
vec![],
);

let receipts = Transactor::new(storage)
let receipts = Transactor::new(storage, Default::default())
.transact(tx)
.receipts()
.expect("Failed to execute script!")
Expand Down Expand Up @@ -171,7 +171,7 @@ fn sha256() {
vec![],
);

let receipts = Transactor::new(storage)
let receipts = Transactor::new(storage, Default::default())
.transact(tx)
.receipts()
.expect("Failed to execute script!")
Expand Down Expand Up @@ -259,7 +259,7 @@ fn keccak256() {
vec![],
);

let receipts = Transactor::new(storage)
let receipts = Transactor::new(storage, Default::default())
.transact(tx)
.receipts()
.expect("Failed to execute script!")
Expand Down
12 changes: 8 additions & 4 deletions tests/flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,9 @@ fn call() {
vec![program.clone()],
);

assert!(Transactor::new(&mut storage).transact(tx).is_success());
assert!(Transactor::new(&mut storage, Default::default())
.transact(tx)
.is_success());

let mut script_ops = vec![
Opcode::MOVI(0x10, 0x00),
Expand Down Expand Up @@ -185,7 +187,7 @@ fn call() {
_ => unreachable!(),
}

let receipts = Transactor::new(&mut storage)
let receipts = Transactor::new(&mut storage, Default::default())
.transact(tx)
.receipts()
.expect("Failed to execute script")
Expand Down Expand Up @@ -243,7 +245,9 @@ fn call_frame_code_offset() {
vec![program.clone().into()],
);

assert!(Transactor::new(&mut storage).transact(deploy).is_success());
assert!(Transactor::new(&mut storage, Default::default())
.transact(deploy)
.is_success());

let input = Input::contract(rng.gen(), rng.gen(), rng.gen(), id);
let output = Output::contract(0, rng.gen(), rng.gen());
Expand Down Expand Up @@ -282,7 +286,7 @@ fn call_frame_code_offset() {
vec![],
);

let mut vm = Interpreter::with_storage(storage);
let mut vm = Interpreter::with_storage(storage, Default::default());

vm.transact(script).expect("Failed to call deployed contract");

Expand Down
Loading