Skip to content

Commit

Permalink
Debug off-by-one error for byte literals.
Browse files Browse the repository at this point in the history
  • Loading branch information
tideofwords committed Jul 14, 2023
1 parent 8db7f10 commit 3f8de92
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 23 deletions.
65 changes: 42 additions & 23 deletions axiom-eth/src/rlp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,17 @@ impl<'range, F: ScalarField> RlpChip<'range, F> {
Existing(is_big),
);

// If item is byte literal, 1
// If item is short, len
// If item is long, len_len
let next_len = self.gate().select(
ctx,
next_len,
Constant(F::one()),
is_not_literal
);


// If item is big, this is the length of the length field
// Else 0
let len_len = self.gate().mul(
Expand Down Expand Up @@ -657,16 +668,6 @@ impl<'range, F: ScalarField> RlpChip<'range, F> {
prefix_parsed.next_len,
prefix_parsed.is_big,
);
self.range.check_less_than_safe(ctx, field_len, (max_field_len + 1) as u64);

let field_cells = witness_subarray(
ctx,
&rlp_array,
&(len_start_id + len_len.value()),
field_len.value(),
max_field_len,
);
running_max_len += 1 + max_field_len_len + max_field_len;

// prefix_len is either 0 or 1
let mut prefix_len = prefix_parsed.is_not_literal;
Expand All @@ -686,9 +687,34 @@ impl<'range, F: ScalarField> RlpChip<'range, F> {
len_len = self.gate().mul(ctx, len_len, field_in_list);
field_len = self.gate().mul(ctx, field_len, field_in_list);
}



self.range.check_less_than_safe(ctx, field_len, (max_field_len + 1) as u64);


let field_cells = witness_subarray(
ctx,
&rlp_array,
&(len_start_id + len_len.value()),
field_len.value(),
max_field_len,
);
running_max_len += 1 + max_field_len_len + max_field_len;

// this is just print for debug
let mut prefix_idx_val = F::from(0u64);
let mut field_len_val = F::from(0u64);

prefix_idx_val = *prefix_idx.value();
field_len_val = *field_len.value();
println!("This field starts at {:?} and has length {:?}", prefix_idx_val.get_lower_32(), field_len_val.get_lower_32());
// end print for debug

prefix = self.gate().mul(ctx, prefix, prefix_len);
prefix_idx = self.gate().sum(ctx, [prefix_idx, prefix_len, len_len, field_len]);


let witness = RlpFieldWitness {
prefix,
prefix_len,
Expand Down Expand Up @@ -721,6 +747,8 @@ impl<'range, F: ScalarField> RlpChip<'range, F> {
let len_trace = rlc.compute_rlc((ctx_gate, ctx_rlc), self.gate(), len_cells, len_len);

let mut field_trace = Vec::with_capacity(field_witness.len());
let mut cml_max_len: usize = 0;

for field_witness in field_witness {
let len_rlc = rlc.compute_rlc(
(ctx_gate, ctx_rlc),
Expand All @@ -740,9 +768,10 @@ impl<'range, F: ScalarField> RlpChip<'range, F> {
len_trace: len_rlc,
field_trace: field_rlc,
});
cml_max_len += field_witness.max_field_len;
}

rlc.load_rlc_cache((ctx_gate, ctx_rlc), self.gate(), bit_length(rlp_array.len() as u64));
rlc.load_rlc_cache((ctx_gate, ctx_rlc), self.gate(), bit_length(cml_max_len as u64));

let prefix = rlp_array[0];
let one = ctx_gate.load_constant(F::one());
Expand Down Expand Up @@ -796,7 +825,6 @@ impl<'range, F: ScalarField> RlpChip<'range, F> {

let len_len = prefix_parsed.len_len;
self.range.check_less_than_safe(ctx, len_len, (max_len_len + 1) as u64);
// why do I need this

// len_byte_val -- len if big, 0 otherwise
let (len_cells, len_byte_val) = self.parse_rlp_len(ctx, &rlp_array, len_len, max_len_len);
Expand Down Expand Up @@ -851,7 +879,6 @@ impl<'range, F: ScalarField> RlpChip<'range, F> {
let mut len_len = prefix_parsed.len_len;
let max_item_len_len = max_rlp_len_len(max_item_len);
self.range.check_less_than_safe(ctx, len_len, (max_item_len_len + 1) as u64);
// why do I need this

let len_start_id = *prefix_parsed.is_not_literal.value() + prefix_idx.value();
// len_cells is empty if phantom, literal, or short
Expand All @@ -869,22 +896,14 @@ impl<'range, F: ScalarField> RlpChip<'range, F> {
// constrained

// len if short or long
// 0 if phantom or literal
// 1 if phantom or literal
let mut item_len = self.gate().select(
ctx,
len_byte_val,
prefix_parsed.next_len,
prefix_parsed.is_big,
);

// len if short or long
// 1 if phantom or literal
item_len = self.gate().select(
ctx,
item_len,
Constant(F::one()),
prefix_parsed.is_not_literal,
);

// prefix_len is 0 if phantom or literal
// 1 otherwise
Expand Down Expand Up @@ -1023,7 +1042,7 @@ impl<'range, F: ScalarField> RlpChip<'range, F> {
}


rlc.load_rlc_cache((ctx_gate, ctx_rlc), self.gate(), cml_max_len);
rlc.load_rlc_cache((ctx_gate, ctx_rlc), self.gate(), bit_length(cml_max_len as u64));

let prefix = rlp_array[0];
let one = ctx_gate.load_constant(F::one());
Expand Down
25 changes: 25 additions & 0 deletions axiom-eth/src/rlp/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,19 @@ mod rlp {
MockProver::run(k, &circuit, vec![]).unwrap().assert_satisfied();
}

#[test] // pass
pub fn test_mock_rlp_array_3() {
let k = DEGREE;
let input_bytes: Vec<u8> = vec![0xc3, 0x00, 0x00, 0x00,];
let circuit = rlp_list_circuit(
RlcThreadBuilder::<Fr>::mock(),
input_bytes,
&[5, 5, 5],
true,
);
MockProver::run(k, &circuit, vec![]).unwrap().assert_satisfied();
}


#[test]
pub fn test_mock_rlp_field() {
Expand Down Expand Up @@ -642,6 +655,18 @@ mod rlp {
MockProver::run(k, &circuit, vec![]).unwrap().assert_satisfied();
}

#[test]
pub fn test_mock_rlp_of_rlp_10() {
let k = DEGREE;
let input_bytes: Vec<u8> = Vec::from_hex("c100000000000000").unwrap();
// list consists of a single string literal
let max_field_lens = vec![100, 100, 100];
let is_var_len = true;

let circuit = rlp_circuit(RlcThreadBuilder::<Fr>::mock(), input_bytes, &max_field_lens, is_var_len);
MockProver::run(k, &circuit, vec![]).unwrap().assert_satisfied();
}




Expand Down

0 comments on commit 3f8de92

Please sign in to comment.