Skip to content

Commit

Permalink
Merge branch 'master' into feature/predicate-verfiicaiton-error
Browse files Browse the repository at this point in the history
  • Loading branch information
xgreenx authored Nov 9, 2023
2 parents ade866a + 694b636 commit d002cff
Show file tree
Hide file tree
Showing 22 changed files with 173 additions and 35 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

#### Breaking

- [#629](https://github.com/FuelLabs/fuel-vm/pull/629): Charge the user for VM initialization.
- [#628](https://github.com/FuelLabs/fuel-vm/pull/628): Renamed `transaction::CheckError` to `transaction::ValidityError`.
Created a new `checked_transaction::CheckError` that combines `ValidityError`
and `PredicateVerificationFailed` errors into one. It allows the return of the
Expand Down Expand Up @@ -43,6 +44,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- If the `max_fee > policies.max_fee`, then transaction will be rejected.
- If the `witnessses_size > policies.witness_limit`, then transaction will be rejected.
- GTF opcode changed its hardcoded constants for fields. It should be updated according to the values from the specification on the Sway side.
- [#633](https://github.com/FuelLabs/fuel-vm/pull/633): Limit receipt count to `u16::MAX`.

### Fixed

Expand Down
7 changes: 5 additions & 2 deletions fuel-asm/src/panic_reason.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ enum_from! {
ExpectedOutputVariable = 0x1d,
/// The expected context of the stack parent is internal.
ExpectedParentInternalContext = 0x1e,
/// The jump instruction cannot move backwards in predicate verification.
IllegalJump = 0x1f,
/// The predicate returned non `1`. The `1` means successful verification
/// of the predicate, all other values means unsuccessful.
PredicateReturnedNonOne = 0x1f,
/// The contract ID is already deployed and can't be overwritten.
ContractIdAlreadyDeployed = 0x20,
/// The loaded contract mismatch expectations.
Expand All @@ -119,6 +120,8 @@ enum_from! {
PolicyIsNotSet = 0x28,
/// The policy is not found across policies.
PolicyNotFound = 0x29,
/// Receipt context is full
TooManyReceipts = 0x2a,
}
}

Expand Down
7 changes: 7 additions & 0 deletions fuel-tx/src/transaction/consensus_parameters/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ pub struct GasCostsValues {
// Non-opcode costs
pub contract_root: DependentCost,
pub state_root: DependentCost,
pub vm_initialization: Word,
}

/// Dependent cost is a cost that depends on the number of units.
Expand Down Expand Up @@ -472,8 +473,11 @@ impl GasCostsValues {
smo: DependentCost::free(),
srwq: DependentCost::free(),
swwq: DependentCost::free(),

// Non-opcode costs
contract_root: DependentCost::free(),
state_root: DependentCost::free(),
vm_initialization: 0,
}
}

Expand Down Expand Up @@ -586,8 +590,11 @@ impl GasCostsValues {
smo: DependentCost::unit(),
srwq: DependentCost::unit(),
swwq: DependentCost::unit(),

// Non-opcode costs
contract_root: DependentCost::unit(),
state_root: DependentCost::unit(),
vm_initialization: 1,
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ pub fn default_gas_costs() -> GasCostsValues {
base: 44,
units_per_gas: 5,
},

// Non-opcode costs
contract_root: DependentCost::LightOperation {
base: 75,
units_per_gas: 1,
Expand All @@ -169,5 +171,6 @@ pub fn default_gas_costs() -> GasCostsValues {
base: 412,
units_per_gas: 1,
},
vm_initialization: 2000,
}
}
4 changes: 3 additions & 1 deletion fuel-tx/src/transaction/fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies {
self.gas_used_by_inputs(gas_costs)
.saturating_add(self.gas_used_by_metadata(gas_costs))
.saturating_add(bytes_gas)
.saturating_add(gas_costs.vm_initialization)
}

/// Returns the maximum possible gas after the end of transaction execution.
Expand Down Expand Up @@ -237,7 +238,8 @@ pub trait Chargeable: field::Inputs + field::Witnesses + field::Policies {
}) => gas_costs
.contract_root
.resolve(predicate.len() as u64)
.saturating_add(*predicate_gas_used),
.saturating_add(*predicate_gas_used)
.saturating_add(gas_costs.vm_initialization),
// Charge nothing for all other inputs
_ => 0,
})
Expand Down
14 changes: 12 additions & 2 deletions fuel-vm/src/checked_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,7 @@ mod tests {

let min_fee = fee.min_fee();
let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte
+ gas_costs.vm_initialization
+ 3 * gas_costs.ecr1
+ gas_costs.s256.resolve(tx.size() as u64))
* gas_price;
Expand Down Expand Up @@ -1060,6 +1061,7 @@ mod tests {
// be recovered once. Therefore, we charge only once for the address
// recovery of the signed inputs.
let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte
+ gas_costs.vm_initialization
+ gas_costs.ecr1
+ gas_costs.s256.resolve(tx.size() as u64))
* gas_price;
Expand Down Expand Up @@ -1124,9 +1126,11 @@ mod tests {

let min_fee = fee.min_fee();
let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte
+ gas_costs.vm_initialization
+ gas_costs.contract_root.resolve(predicate_1.len() as u64)
+ gas_costs.contract_root.resolve(predicate_2.len() as u64)
+ gas_costs.contract_root.resolve(predicate_3.len() as u64)
+ 3 * gas_costs.vm_initialization
+ 50
+ 100
+ 200
Expand Down Expand Up @@ -1208,9 +1212,11 @@ mod tests {
let min_fee = fee.min_fee();
let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte
+ 3 * gas_costs.ecr1
+ gas_costs.vm_initialization
+ gas_costs.contract_root.resolve(predicate_1.len() as u64)
+ gas_costs.contract_root.resolve(predicate_2.len() as u64)
+ gas_costs.contract_root.resolve(predicate_3.len() as u64)
+ 3 * gas_costs.vm_initialization
+ 50
+ 100
+ 200
Expand Down Expand Up @@ -1248,6 +1254,7 @@ mod tests {
let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte
+ gas_costs.state_root.resolve(storage_slots_len as Word)
+ gas_costs.contract_root.resolve(bytecode_len as Word)
+ gas_costs.vm_initialization
+ gas_costs.s256.resolve(100)
+ gas_costs.s256.resolve(tx.size() as u64))
* gas_price;
Expand Down Expand Up @@ -1280,6 +1287,7 @@ mod tests {
let expected_min_fee = (tx.metered_bytes_size() as u64 * fee_params.gas_per_byte
+ gas_costs.state_root.resolve(0)
+ gas_costs.contract_root.resolve(0)
+ gas_costs.vm_initialization
+ gas_costs.s256.resolve(100)
+ gas_costs.s256.resolve(tx.size() as u64))
* gas_price;
Expand Down Expand Up @@ -1567,7 +1575,8 @@ mod tests {
let gas_used_by_metadata = tx.gas_used_by_metadata(gas_costs);
let min_gas = gas_used_by_bytes
.saturating_add(gas_used_by_inputs)
.saturating_add(gas_used_by_metadata);
.saturating_add(gas_used_by_metadata)
.saturating_add(gas_costs.vm_initialization);

// use different division mechanism than impl
let witness_limit_allowance = tx
Expand Down Expand Up @@ -1605,7 +1614,8 @@ mod tests {
let gas_used_by_metadata = tx.gas_used_by_metadata(gas_costs);
let gas = gas_used_by_bytes
.saturating_add(gas_used_by_inputs)
.saturating_add(gas_used_by_metadata);
.saturating_add(gas_used_by_metadata)
.saturating_add(gas_costs.vm_initialization);
let total = gas as u128 * tx.price() as u128;
// use different division mechanism than impl
let fee = total / fee_params.gas_price_factor as u128;
Expand Down
4 changes: 4 additions & 0 deletions fuel-vm/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ pub enum BugVariant {
/// Refund cannot be computed in the current vm state.
#[strum(message = "Refund cannot be computed in the current vm state.")]
UncomputableRefund,

/// Receipts context is full, but there's an attempt to add more receipts.
#[strum(message = "Receipts context is full, cannot add new receipts.")]
ReceiptsCtxFull,
}

impl fmt::Display for BugVariant {
Expand Down
6 changes: 3 additions & 3 deletions fuel-vm/src/interpreter/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ where

let receipt = Receipt::burn(*sub_id, *contract_id, a, *self.pc, *self.is);

append_receipt(self.append, receipt);
append_receipt(self.append, receipt)?;

Ok(inc_pc(self.pc)?)
}
Expand Down Expand Up @@ -660,7 +660,7 @@ where

let receipt = Receipt::mint(*sub_id, *contract_id, a, *self.pc, *self.is);

append_receipt(self.append, receipt);
append_receipt(self.append, receipt)?;

Ok(inc_pc(self.pc)?)
}
Expand Down Expand Up @@ -1021,7 +1021,7 @@ where
memory: self.memory,
},
receipt,
);
)?;

Ok(inc_pc(self.pc)?)
}
Expand Down
4 changes: 2 additions & 2 deletions fuel-vm/src/interpreter/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ impl<'vm, S, Tx> TransferCtx<'vm, S, Tx> {
memory: self.memory,
},
receipt,
);
)?;

Ok(inc_pc(self.pc)?)
}
Expand Down Expand Up @@ -340,7 +340,7 @@ impl<'vm, S, Tx> TransferCtx<'vm, S, Tx> {
memory: self.memory,
},
receipt,
);
)?;

Ok(inc_pc(self.pc)?)
}
Expand Down
2 changes: 1 addition & 1 deletion fuel-vm/src/interpreter/diff/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ fn reset_vm_state_receipts() {
Default::default(),
Default::default(),
);
b.receipts.push(receipt);
b.receipts.push(receipt).expect("not full");
assert_ne!(a.receipts, b.receipts);
let diff: Diff<InitialVmState> = a.diff(&b).into();
b.reset_vm_state(&diff);
Expand Down
2 changes: 1 addition & 1 deletion fuel-vm/src/interpreter/executors/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ where
self.gas_charge(self.gas_costs().rvrt)?;
let a = rvrt.unpack();
let ra = r!(a);
self.revert(ra);
self.revert(ra)?;
return Ok(ExecuteState::Revert(ra))
}

Expand Down
2 changes: 1 addition & 1 deletion fuel-vm/src/interpreter/executors/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ where

let receipt = Receipt::script_result(status, gas_used);

self.append_receipt(receipt);
self.append_receipt(receipt)?;

if program.is_debug() {
self.debugger_set_last_state(program);
Expand Down
2 changes: 1 addition & 1 deletion fuel-vm/src/interpreter/executors/predicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ where
if r == 1 {
return Ok(ProgramState::Return(r))
} else {
return Err(PanicReason::ContractInstructionNotAllowed.into())
return Err(PanicReason::PredicateReturnedNonOne.into())
}
}

Expand Down
13 changes: 7 additions & 6 deletions fuel-vm/src/interpreter/flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ where
input.ret_data(a, b)
}

pub(crate) fn revert(&mut self, a: Word) {
pub(crate) fn revert(&mut self, a: Word) -> SimpleResult<()> {
let current_contract =
current_contract(&self.context, self.registers.fp(), self.memory.as_ref())
.map_or_else(|_| Some(ContractId::zeroed()), Option::<&_>::copied);
Expand Down Expand Up @@ -172,7 +172,8 @@ where
};
self.panic_context = PanicContext::None;

self.append_receipt(receipt);
self.append_receipt(receipt)
.expect("Appending a panic receipt cannot fail");
}
}

Expand Down Expand Up @@ -227,7 +228,7 @@ impl RetCtx<'_> {
set_frame_pointer(context, registers.fp_mut(), fp);
}

append_receipt(self.append, receipt);
append_receipt(self.append, receipt)?;

Ok(inc_pc(self.registers.pc_mut())?)
}
Expand Down Expand Up @@ -261,15 +262,15 @@ pub(crate) fn revert(
pc: Reg<PC>,
is: Reg<IS>,
a: Word,
) {
) -> SimpleResult<()> {
let receipt = Receipt::revert(
current_contract.unwrap_or_else(ContractId::zeroed),
a,
*pc,
*is,
);

append_receipt(append, receipt);
append_receipt(append, receipt)
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -628,7 +629,7 @@ where
memory: self.memory.memory,
},
receipt,
);
)?;

self.frames.push(frame);

Expand Down
2 changes: 1 addition & 1 deletion fuel-vm/src/interpreter/flow/ret_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ fn test_revert() {
};
let pc = 10;
let is = 20;
revert(append, None, Reg::new(&pc), Reg::new(&is), 99);
revert(append, None, Reg::new(&pc), Reg::new(&is), 99).expect("should be ok");
assert_eq!(
*receipts.as_ref().last().unwrap(),
Receipt::revert(ContractId::default(), 99, pc, is)
Expand Down
8 changes: 5 additions & 3 deletions fuel-vm/src/interpreter/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ where
update_memory_output(&mut self.tx, &mut self.memory, tx_offset, idx)
}

pub(crate) fn append_receipt(&mut self, receipt: Receipt) {
pub(crate) fn append_receipt(&mut self, receipt: Receipt) -> SimpleResult<()> {
let tx_offset = self.tx_offset();
append_receipt(
AppendReceipt {
Expand Down Expand Up @@ -128,14 +128,14 @@ pub(crate) struct AppendReceipt<'vm> {
pub memory: &'vm mut [u8; MEM_SIZE],
}

pub(crate) fn append_receipt(input: AppendReceipt, receipt: Receipt) {
pub(crate) fn append_receipt(input: AppendReceipt, receipt: Receipt) -> SimpleResult<()> {
let AppendReceipt {
receipts,
script,
tx_offset,
memory,
} = input;
receipts.push(receipt);
receipts.push(receipt)?;

if let Some(script) = script {
let offset = tx_offset + script.receipts_root_offset();
Expand All @@ -151,6 +151,8 @@ pub(crate) fn append_receipt(input: AppendReceipt, receipt: Receipt) {
// guaranteed to fit
memory[offset..offset + Bytes32::LEN].copy_from_slice(&root[..]);
}

Ok(())
}

impl<S, Tx, Ecal> Interpreter<S, Tx, Ecal> {
Expand Down
4 changes: 2 additions & 2 deletions fuel-vm/src/interpreter/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl LogInput<'_> {
memory: self.memory,
},
receipt,
);
)?;

Ok(inc_pc(self.pc)?)
}
Expand All @@ -128,7 +128,7 @@ impl LogInput<'_> {
memory: self.memory,
},
receipt,
);
)?;

Ok(inc_pc(self.pc)?)
}
Expand Down
Loading

0 comments on commit d002cff

Please sign in to comment.