Skip to content

Commit

Permalink
fix!: Disallow trailing xfe in poly encoding to be zero
Browse files Browse the repository at this point in the history
This closes #98.
  • Loading branch information
Sword-Smith committed Apr 30, 2024
1 parent 60fd949 commit 9f7600a
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 18 deletions.
16 changes: 8 additions & 8 deletions tasm-lib/benchmarks/tasmlib_verifier_fri_verify.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@
{
"name": "tasmlib_verifier_fri_verify",
"benchmark_result": {
"clock_cycle_count": 126123,
"hash_table_height": 14808,
"clock_cycle_count": 126151,
"hash_table_height": 14838,
"u32_table_height": 12046,
"op_stack_table_height": 125205,
"ram_table_height": 19393
"op_stack_table_height": 125233,
"ram_table_height": 19397
},
"case": "CommonCase"
},
{
"name": "tasmlib_verifier_fri_verify",
"benchmark_result": {
"clock_cycle_count": 126123,
"hash_table_height": 14808,
"clock_cycle_count": 126151,
"hash_table_height": 14838,
"u32_table_height": 11671,
"op_stack_table_height": 125205,
"ram_table_height": 19393
"op_stack_table_height": 125233,
"ram_table_height": 19397
},
"case": "WorstCase"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
{
"name": "tasmlib_verifier_stark_verify_inner_padded_height_256_fri_exp_4",
"benchmark_result": {
"clock_cycle_count": 936617,
"hash_table_height": 181813,
"u32_table_height": 17367,
"op_stack_table_height": 1388098,
"ram_table_height": 479717
"clock_cycle_count": 936645,
"hash_table_height": 181837,
"u32_table_height": 17407,
"op_stack_table_height": 1388126,
"ram_table_height": 479721
},
"case": "CommonCase"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
{
"name": "tasmlib_verifier_stark_verify_inner_padded_height_512_fri_exp_4",
"benchmark_result": {
"clock_cycle_count": 960560,
"hash_table_height": 190945,
"u32_table_height": 22311,
"op_stack_table_height": 1421616,
"ram_table_height": 482199
"clock_cycle_count": 960588,
"hash_table_height": 190969,
"u32_table_height": 23160,
"op_stack_table_height": 1421644,
"ram_table_height": 482203
},
"case": "CommonCase"
}
Expand Down
1 change: 1 addition & 0 deletions tasm-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ pub fn execute_with_terminal_state(
vm_state.op_stack.stack = stack.to_owned();
vm_state.sponge = maybe_sponge;

maybe_write_debuggable_program_to_disk(program, &vm_state);
match vm_state.run() {
Ok(()) => {
println!("Triton VM execution successful.");
Expand Down
143 changes: 143 additions & 0 deletions tasm-lib/src/verifier/vm_proof_iter/dequeue_next_as.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use triton_vm::prelude::*;
use triton_vm::proof_item::ProofItemVariant;
use triton_vm::twenty_first::math::x_field_element::EXTENSION_DEGREE;

use crate::data_type::DataType;
use crate::hashing::sponge_hasher::pad_and_absorb_all::PadAndAbsorbAll;
Expand Down Expand Up @@ -128,6 +129,62 @@ impl DequeueNextAs {

triton_asm! { push {bookkeeping_offset} hint bookkeeping_offset = stack[0] add }
}

/// A `BFielcCodec`` encoding of a `Polynomial<T>` may not contain trailing zeros. This is
/// because it must be easy to read the degree of the polynomial. In order to be consistent with
/// that rule, we perform this check here, before returning a pointer to the polynomial to the
/// caller.
/// ```text
/// BEFORE: _ *proof_item_payload
/// AFTER: _ *proof_item_payload
/// ```
fn verify_last_xfe_is_non_zero_if_payload_is_polynomial(&self) -> Vec<LabelledInstruction> {
match self.proof_item {
ProofItemVariant::FriPolynomial => triton_asm!(
// _ *fri_polynomial

dup 0
push 1
add
read_mem 1
pop 1
// _ *fri_polynomial num_coefficients

push {EXTENSION_DEGREE}
mul
push 1
add
// _ *fri_polynomial offset_last_word

dup 1
add
// _ *proof_item_payload *coefficients_last_word

read_mem {EXTENSION_DEGREE}
pop 1
push 0
eq
swap 2
push 0
eq
swap 1
push 0
eq
add
add
push {EXTENSION_DEGREE}
eq
// _ *proof_item_payload (last_coefficient == 0)

push 0
eq
// _ *proof_item_payload (last_coefficient != 0)

assert
),
_ => triton_asm!(),
}
}
}

impl BasicSnippet for DequeueNextAs {
Expand Down Expand Up @@ -180,6 +237,10 @@ impl BasicSnippet for DequeueNextAs {

{&self.advance_list_element_pointer_to_proof_item_payload()}
{final_hint} // _ *proof_item_payload

{&self.verify_last_xfe_is_non_zero_if_payload_is_polynomial()}
{final_hint} // _ *proof_item_payload

return
}
}
Expand All @@ -203,6 +264,7 @@ mod test {
use triton_vm::proof_item::ProofItem;
use triton_vm::proof_stream::ProofStream;
use triton_vm::table::NUM_BASE_COLUMNS;
use triton_vm::twenty_first::math::polynomial::Polynomial;

use crate::empty_stack;
use crate::execute_with_terminal_state;
Expand Down Expand Up @@ -493,6 +555,87 @@ mod test {
DequeueNextAs::initial_state_from_proof_stream_and_address(proof_stream, address)
}

#[test]
fn disallow_trailing_zeros_in_xfe_poly_encoding() {
let dequeue_next_as = DequeueNextAs::new(ProofItemVariant::FriPolynomial);
let initial_state = initial_state_with_trailing_zeros_in_xfe_poly_encoding();
let code = link_for_isolated_run(Rc::new(RefCell::new(dequeue_next_as)));
let program = Program::new(&code);
let tvm_result = execute_with_terminal_state(
&program,
&[],
&initial_state.stack,
&initial_state.nondeterminism,
None,
);

let rust_result = std::panic::catch_unwind(|| {
let mut stack = initial_state.stack.clone();
let mut memory = initial_state.nondeterminism.ram.clone();
dequeue_next_as.rust_shadow(
&mut stack,
&mut memory,
&NonDeterminism::default(),
&[],
&mut None,
);
});

assert!(
rust_result.is_err() && tvm_result.is_err(),
"Test case: Too big dynamically-sized proof item must fail on both platforms."
);
let err = tvm_result.unwrap_err();
assert_eq!(InstructionError::AssertionFailed, err);
}

fn initial_state_with_trailing_zeros_in_xfe_poly_encoding() -> ProcedureInitialState {
let mut encoded_fri_poly_proof_item =
ProofItem::FriPolynomial(Polynomial::new(vec![xfe!(1), xfe!(2), xfe!(3), xfe!(100)]))
.encode();

// Manually set the leading coefficient to zero
let encoding_length = encoded_fri_poly_proof_item.len();
for i in 0..EXTENSION_DEGREE {
encoded_fri_poly_proof_item[encoding_length - 1 - i] = bfe!(0);
}

let proof_start_address = BFieldElement::zero();

let mut ram = HashMap::new();

let mut address = proof_start_address;

// Inidicate a field-size of `ProofStream`
ram.insert(address, bfe!(encoding_length as u64 + 2));
address.increment();

// Indicate that there is one proof item
ram.insert(address, bfe!(1));
address.increment();

// Indicate size of encoded proof item
ram.insert(address, bfe!(encoding_length as u64));
address.increment();

// Add proof item to ND memory
for word in encoded_fri_poly_proof_item {
ram.insert(address, word);
address.increment();
}

// uses highly specific knowledge of `BFieldCodec`
let address_of_first_element = proof_start_address + BFieldElement::new(2);
let proof_iter_address = proof_start_address - BFieldElement::one();
ram.insert(proof_iter_address, address_of_first_element);
ProcedureInitialState {
stack: [empty_stack(), vec![proof_iter_address]].concat(),
nondeterminism: NonDeterminism::default().with_ram(ram),
public_input: vec![],
sponge: Some(Tip5::init()),
}
}

#[test]
fn dequeueing_a_merkle_root_is_equivalent_in_rust_and_tasm() {
let dequeue_next_as = DequeueNextAs::new(ProofItemVariant::MerkleRoot);
Expand Down

0 comments on commit 9f7600a

Please sign in to comment.