Skip to content

Commit

Permalink
feat!: instruction hash only puts digest on stack
Browse files Browse the repository at this point in the history
Notably, the top of the stack in not polluted with spurious 0s.

BREAKING CHANGE: executing instruction `hash` shrinks the stack by 5
  • Loading branch information
jan-ferdinand committed Oct 30, 2023
1 parent 6215c10 commit 2e37fb2
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 158 deletions.
2 changes: 1 addition & 1 deletion opcodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def in_bucket(instruction_bucket, instruction):
return instruction in [Instruction.Push, Instruction.Dup, Instruction.Swap, Instruction.Call]
if instruction_bucket == InstructionBucket.ShrinkStack:
return instruction in [Instruction.Pop, Instruction.Skiz, Instruction.Assert, Instruction.WriteMem, Instruction.WriteIo,
Instruction.Add, Instruction.Mul, Instruction.Eq, Instruction.XbMul,
Instruction.Add, Instruction.Mul, Instruction.Eq, Instruction.XbMul, Instruction.Hash,
Instruction.Lt, Instruction.And, Instruction.Xor, Instruction.Pow]
if instruction_bucket == InstructionBucket.U32:
return instruction in [Instruction.Lt, Instruction.And, Instruction.Xor, Instruction.Log2Floor,
Expand Down
24 changes: 11 additions & 13 deletions triton-vm/src/example_programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,39 +138,38 @@ fn merkle_tree_authentication_path_verify() -> Program {
push -1 add write_mem pop // decrease number of authentication paths left to check
// stack: [* r4 r3 r2 r1 r0]
call get_idx_and_leaf
// stack: [* r4 r3 r2 r1 r0 idx d4 d3 d2 d1 d0 0 0 0 0 0]
// stack: [* r4 r3 r2 r1 r0 idx l4 l3 l2 l1 l0]
call traverse_tree
// stack: [* r4 r3 r2 r1 r0 idx>>1 - - - - - - - - - -]
// stack: [* r4 r3 r2 r1 r0 1 d4 d3 d2 d1 d0]
call assert_tree_top
// stack: [* r4 r3 r2 r1 r0]
recurse // check next AP

// subroutine: read index & hash leaf
// stack before: [*]
// stack after: [* idx d4 d3 d2 d1 d0 0 0 0 0 0]
// stack after: [* idx l4 l3 l2 l1 l0]
get_idx_and_leaf:
read_io // read node index
read_io read_io read_io read_io read_io // read leaf's value
push 0 push 0 push 0 push 0 push 0 // pad for instruction divine_sibling
return

// subroutine: go up tree
// stack before: [* idx - - - - - - - - - -]
// stack after: [* idx>>1 - - - - - - - - - -]
// stack before: [* r4 r3 r2 r1 r0 idx l4 l3 l2 l1 l0]
// stack after: [* r4 r3 r2 r1 r0 1 d4 d3 d2 d1 d0]
traverse_tree:
dup 10 push 1 eq skiz return // break loop if node index is 1
dup 5 push 1 eq skiz return // break loop if node index is 1
push 0 push 0 push 0 push 0 push 0 // prepare for instruction `divine_sibling`
divine_sibling hash recurse // move up one level in the Merkle tree

// subroutine: compare digests
// stack before: [* r4 r3 r2 r1 r0 idx a b c d e - - - - -]
// stack before: [* r4 r3 r2 r1 r0 1 d4 d3 d2 d1 d0]
// stack after: [* r4 r3 r2 r1 r0]
assert_tree_top:
pop pop pop pop pop // remove unnecessary “0”s from hashing
// stack: [* r4 r3 r2 r1 r0 idx a b c d e]
// stack: [* r4 r3 r2 r1 r0 1 d4 d3 d2 d1 d0]
swap 1 swap 2 swap 3 swap 4 swap 5
// stack: [* r4 r3 r2 r1 r0 a b c d e idx]
// stack: [* r4 r3 r2 r1 r0 d4 d3 d2 d1 d0 1]
assert // ensure the entire path was traversed
// stack: [* r4 r3 r2 r1 r0 a b c d e]
// stack: [* r4 r3 r2 r1 r0 d4 d3 d2 d1 d0]
assert_vector // actually compare to root of tree
pop pop pop pop pop // clean up stack, leave only one root
return
Expand Down Expand Up @@ -545,7 +544,6 @@ pub(crate) fn calculate_new_mmr_peaks_from_append_with_safe_lists() -> Program {
// Stack: _ old_leaf_count_hi old_leaf_count_lo rll *auth_path *peaks *peaks [digest (new_hash)] [digests (previous_peak)]

hash
pop pop pop pop pop
// Stack: _ old_leaf_count_hi old_leaf_count_lo rll *auth_path *peaks *peaks [digests (new_peak)]

call tasm_list_safe_u32_push_digest
Expand Down
37 changes: 17 additions & 20 deletions triton-vm/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,16 +170,16 @@ impl<Dest: PartialEq + Default> AnInstruction<Dest> {
Halt => 0,
ReadMem => 40,
WriteMem => 26,
Hash => 48,
DivineSibling => 56,
AssertVector => 64,
SpongeInit => 72,
SpongeAbsorb => 80,
SpongeSqueeze => 88,
Add => 34,
Mul => 42,
Invert => 96,
Eq => 50,
Hash => 34,
DivineSibling => 48,
AssertVector => 56,
SpongeInit => 64,
SpongeAbsorb => 72,
SpongeSqueeze => 80,
Add => 42,
Mul => 50,
Invert => 88,
Eq => 58,
Split => 4,
Lt => 6,
And => 14,
Expand All @@ -188,12 +188,12 @@ impl<Dest: PartialEq + Default> AnInstruction<Dest> {
Pow => 30,
DivMod => 20,
PopCount => 28,
XxAdd => 104,
XxMul => 112,
XInvert => 120,
XbMul => 58,
ReadIo => 128,
WriteIo => 66,
XxAdd => 96,
XxMul => 104,
XInvert => 112,
XbMul => 66,
ReadIo => 120,
WriteIo => 74,
}
}

Expand Down Expand Up @@ -334,7 +334,7 @@ impl<Dest: PartialEq + Default> AnInstruction<Dest> {
Halt => 0,
ReadMem => 1,
WriteMem => -1,
Hash => 0,
Hash => -5,
DivineSibling => 0,
AssertVector => 0,
SpongeInit => 0,
Expand Down Expand Up @@ -522,7 +522,6 @@ pub enum InstructionBit {
IB4,
IB5,
IB6,
IB7,
}

impl Display for InstructionBit {
Expand All @@ -542,7 +541,6 @@ impl From<InstructionBit> for usize {
IB4 => 4,
IB5 => 5,
IB6 => 6,
IB7 => 7,
}
}
}
Expand All @@ -559,7 +557,6 @@ impl TryFrom<usize> for InstructionBit {
4 => Ok(IB4),
5 => Ok(IB5),
6 => Ok(IB6),
7 => Ok(IB7),
_ => Err(format!(
"Index {bit_index} is out of range for `InstructionBit`."
)),
Expand Down
2 changes: 1 addition & 1 deletion triton-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ mod tests {
// Program proves the knowledge of a hash preimage
let program = triton_program!(
divine divine divine divine divine
hash pop pop pop pop pop
hash
push 09456474867485907852
push 12765666850723567758
push 08551752384389703074
Expand Down
Loading

0 comments on commit 2e37fb2

Please sign in to comment.