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 push/pop instructions #498

Merged
merged 12 commits into from
Aug 8, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ The release mostly fixes funding during the audit and integration with the bridg

- [#486](https://github.com/FuelLabs/fuel-vm/pull/486/): Adds `ed25519` signature verification and `secp256r1` signature recovery to `fuel-crypto`, and corresponding opcodes `ED19` and `ECR1` to `fuel-vm`.

- [#486](https://github.com/FuelLabs/fuel-vm/pull/498): Adds `PSHL`, `PSHH`, `POPH` and `POPL` instructions, which allow cheap push and pop stack operations with multiple registers.

- [#500](https://github.com/FuelLabs/fuel-vm/pull/500): Introduced `ParallelExecutor` trait
and made available async versions of verify and estimate predicates.
Updated tests to test for both parallel and sequential execution.
Expand Down
2 changes: 1 addition & 1 deletion fuel-asm/src/encoding_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn opcode() {

for opcode_int in 0..64 {
let Ok(op) = Opcode::try_from(opcode_int) else {
continue;
continue
};

instructions.push(op.test_construct(r, r, r, r, imm12));
Expand Down
20 changes: 14 additions & 6 deletions fuel-asm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,14 @@ impl_instructions! {
0x93 CFE cfe [amount: RegId]
"Shrink the current call frame's stack"
0x94 CFS cfs [amount: RegId]
"Push a bitmask-selected set of registers in range 16..40 to the stack."
0x95 PSHL pshl [bitmask: Imm24]
"Push a bitmask-selected set of registers in range 40..64 to the stack."
0x96 PSHH pshh [bitmask: Imm24]
"Pop a bitmask-selected set of registers in range 16..40 to the stack."
0x97 POPL popl [bitmask: Imm24]
"Pop a bitmask-selected set of registers in range 40..64 to the stack."
0x98 POPH poph [bitmask: Imm24]

"Compare 128bit integers"
0xa0 WDCM wdcm [dst: RegId lhs: RegId rhs: RegId flags: Imm06]
Expand Down Expand Up @@ -492,12 +500,12 @@ impl Opcode {
match self {
ADD | AND | DIV | EQ | EXP | GT | LT | MLOG | MROO | MOD | MOVE | MUL
| NOT | OR | SLL | SRL | SUB | XOR | WDCM | WQCM | WDOP | WQOP | WDML
| WQML | WDDV | WQDV | WDMD | WQMD | WDAM | WQAM | WDMM | WQMM | RET
| ALOC | MCL | MCP | MEQ | ECK1 | ECR1 | ED19 | K256 | S256 | NOOP | FLAG
| ADDI | ANDI | DIVI | EXPI | MODI | MULI | MLDV | ORI | SLLI | SRLI
| SUBI | XORI | JNEI | LB | LW | SB | SW | MCPI | MCLI | GM | MOVI | JNZI
| JI | JMP | JNE | JMPF | JMPB | JNZF | JNZB | JNEF | JNEB | CFEI | CFSI
| CFE | CFS | GTF => true,
| WQML | WDDV | WQDV | WDMD | WQMD | WDAM | WQAM | WDMM | WQMM | PSHH
| PSHL | POPH | POPL | RET | ALOC | MCL | MCP | MEQ | ECK1 | ECR1 | ED19
| K256 | S256 | NOOP | FLAG | ADDI | ANDI | DIVI | EXPI | MODI | MULI
| MLDV | ORI | SLLI | SRLI | SUBI | XORI | JNEI | LB | LW | SB | SW
| MCPI | MCLI | GM | MOVI | JNZI | JI | JMP | JNE | JMPF | JMPB | JNZF
| JNZB | JNEF | JNEB | CFEI | CFSI | CFE | CFS | GTF => true,
_ => false,
}
}
Expand Down
4 changes: 2 additions & 2 deletions fuel-crypto/src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ pub fn verify(
message: &Message,
) -> Result<(), Error> {
let Ok(signature) = Signature::from_bytes(&**signature) else {
return Err(Error::InvalidSignature);
return Err(Error::InvalidSignature)
};

let Ok(pub_key) = ed25519_dalek::PublicKey::from_bytes(&**pub_key) else {
return Err(Error::InvalidPublicKey);
return Err(Error::InvalidPublicKey)
};

if pub_key.verify_strict(&**message, &signature).is_ok() {
Expand Down
37 changes: 35 additions & 2 deletions fuel-vm/src/constraints/reg_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,9 @@ impl<'r> ProgramRegisters<'r> {
// Translate the `a` absolute register index to a program register index.
let a = a.translate();
// Split the array at the first register which is a.
let [i, rest @ ..] = &mut self.0[a..] else { return None };
let [i, rest @ ..] = &mut self.0[a..] else {
return None
};
// Translate the `b` absolute register index to a program register index.
// Subtract 1 because the first register is `a`.
// Subtract `a` registers because we split the array at `a`.
Expand All @@ -303,7 +305,9 @@ impl<'r> ProgramRegisters<'r> {
// Translate the `b` absolute register index to a program register index.
let b = b.translate();
// Split the array at the first register which is b.
let [i, rest @ ..] = &mut self.0[b..] else { return None };
let [i, rest @ ..] = &mut self.0[b..] else {
return None
};
// Translate the `a` absolute register index to a program register index.
// Subtract 1 because the first register is `b`.
// Subtract `b` registers because we split the array at `b`.
Expand Down Expand Up @@ -422,3 +426,32 @@ impl<'a> From<&SystemRegistersRef<'a>> for [Word; VM_REGISTER_SYSTEM_COUNT] {
]
}
}

#[derive(Debug, Clone, Copy)]
pub(crate) enum ProgramRegistersSegment {
/// Registers 16..40
Low,
/// Registers 40..64
High,
}

impl<'r> ProgramRegisters<'r> {
/// Returns the registers corresponding to the segment, always 24 elements.
pub(crate) fn segment(&self, segment: ProgramRegistersSegment) -> &[Word] {
match segment {
ProgramRegistersSegment::Low => &self.0[..24],
ProgramRegistersSegment::High => &self.0[24..],
}
}

/// Returns the registers corresponding to the segment, always 24 elements.
pub(crate) fn segment_mut(
&mut self,
segment: ProgramRegistersSegment,
) -> &mut [Word] {
match segment {
ProgramRegistersSegment::Low => &mut self.0[..24],
ProgramRegistersSegment::High => &mut self.0[24..],
}
}
}
12 changes: 12 additions & 0 deletions fuel-vm/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ pub struct GasCostsValues {
pub not: Word,
pub or: Word,
pub ori: Word,
pub poph: Word,
pub popl: Word,
pub pshh: Word,
pub pshl: Word,
#[cfg_attr(feature = "serde", serde(rename = "ret_contract"))]
pub ret: Word,
#[cfg_attr(feature = "serde", serde(rename = "rvrt_contract"))]
Expand Down Expand Up @@ -376,6 +380,10 @@ impl GasCostsValues {
not: 0,
or: 0,
ori: 0,
poph: 0,
popl: 0,
pshh: 0,
pshl: 0,
ret: 0,
rvrt: 0,
s256: 0,
Expand Down Expand Up @@ -485,6 +493,10 @@ impl GasCostsValues {
or: 1,
ori: 1,
ret: 1,
poph: 1,
popl: 1,
pshh: 1,
pshl: 1,
rvrt: 1,
s256: 1,
sb: 1,
Expand Down
4 changes: 4 additions & 0 deletions fuel-vm/src/gas/default_gas_costs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ pub fn default_gas_costs() -> GasCostsValues {
not: 1,
or: 1,
ori: 1,
poph: 2,
popl: 2,
pshh: 2,
pshl: 2,
move_op: 1,
ret: 63,
s256: 4,
Expand Down
25 changes: 25 additions & 0 deletions fuel-vm/src/interpreter/executors/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
constraints::reg_key::ProgramRegistersSegment,
consts::*,
error::{
InterpreterError,
Expand Down Expand Up @@ -625,6 +626,30 @@ where
self.stack_pointer_overflow(Word::overflowing_sub, r!(a))?;
}

Instruction::PSHL(pshl) => {
self.gas_charge(self.gas_costs.pshl)?;
let bitmask = pshl.unpack();
self.push_selected_registers(ProgramRegistersSegment::Low, bitmask)?;
}

Instruction::PSHH(pshh) => {
self.gas_charge(self.gas_costs.pshh)?;
let bitmask = pshh.unpack();
self.push_selected_registers(ProgramRegistersSegment::High, bitmask)?;
}

Instruction::POPL(popl) => {
self.gas_charge(self.gas_costs.popl)?;
let bitmask = popl.unpack();
self.pop_selected_registers(ProgramRegistersSegment::Low, bitmask)?;
}

Instruction::POPH(poph) => {
self.gas_charge(self.gas_costs.poph)?;
let bitmask = poph.unpack();
self.pop_selected_registers(ProgramRegistersSegment::High, bitmask)?;
}

Instruction::LB(lb) => {
self.gas_charge(self.gas_costs.lb)?;
let (a, b, imm) = lb.unpack();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ fn writes_to_ra(opcode: Opcode) -> bool {
Opcode::NOT => true,
Opcode::OR => true,
Opcode::ORI => true,
Opcode::POPH => false,
Opcode::POPL => false,
Opcode::PSHH => false,
Opcode::PSHL => false,
Opcode::SLL => true,
Opcode::SLLI => true,
Opcode::SRL => true,
Expand Down Expand Up @@ -232,6 +236,10 @@ fn writes_to_rb(opcode: Opcode) -> bool {
Opcode::NOT => false,
Opcode::OR => false,
Opcode::ORI => false,
Opcode::POPH => false,
Opcode::POPL => false,
Opcode::PSHH => false,
Opcode::PSHL => false,
Opcode::SLL => false,
Opcode::SLLI => false,
Opcode::SRL => false,
Expand Down
4 changes: 3 additions & 1 deletion fuel-vm/src/interpreter/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,9 @@ pub(crate) fn set_flag(
pc: RegMut<PC>,
a: Word,
) -> Result<(), RuntimeError> {
let Some(flags) = Flags::from_bits(a) else { return Err(PanicReason::ErrorFlag.into()) };
let Some(flags) = Flags::from_bits(a) else {
return Err(PanicReason::ErrorFlag.into())
};

*flag = flags.bits();

Expand Down
Loading