diff --git a/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call/blackbox.rs b/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call/blackbox.rs index 21179a08faa..d80f49b4119 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call/blackbox.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dfg/simplify/call/blackbox.rs @@ -180,11 +180,17 @@ pub(super) fn simplify_msm( var_points.push(result_is_infinity); } // Construct the simplified MSM expression - let typ = Type::Array(Arc::new(vec![Type::field()]), var_scalars.len() as u32); + let typ = Type::Array( + Arc::new(vec![Type::field(), Type::field()]), + var_scalars.len() as u32 / 2, + ); let scalars = Instruction::MakeArray { elements: var_scalars.into(), typ }; let scalars = dfg.insert_instruction_and_results(scalars, block, None, call_stack).first(); - let typ = Type::Array(Arc::new(vec![Type::field()]), var_points.len() as u32); + let typ = Type::Array( + Arc::new(vec![Type::field(), Type::field(), Type::bool()]), + var_points.len() as u32 / 3, + ); let points = Instruction::MakeArray { elements: var_points.into(), typ }; let points = dfg.insert_instruction_and_results(points, block, None, call_stack).first(); @@ -367,8 +373,8 @@ mod multi_scalar_mul { let src = r#" acir(inline) fn main f0 { b0(): - v0 = make_array [Field 2, Field 3, Field 5, Field 5] : [Field; 4] - v1 = make_array [Field 1, Field 17631683881184975370165255887551781615748388533673675138860, Field 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, Field 0] : [Field; 6] + v0 = make_array [Field 2, Field 3, Field 5, Field 5] : [(Field, Field); 2] + v1 = make_array [Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0] : [(Field, Field, u1); 2] v2 = call multi_scalar_mul (v1, v0) -> [(Field, Field, u1); 1] return v2 }"#; @@ -377,10 +383,10 @@ mod multi_scalar_mul { assert_ssa_snapshot!(ssa, @r" acir(inline) fn main f0 { b0(): - v3 = make_array [Field 2, Field 3, Field 5, Field 5] : [Field; 4] - v7 = make_array [Field 1, Field 17631683881184975370165255887551781615748388533673675138860, Field 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, Field 0] : [Field; 6] - v11 = make_array [Field 1478523918288173385110236399861791147958001875200066088686689589556927843200, Field 700144278551281040379388961242974992655630750193306467120985766322057145630, u1 0] : [(Field, Field, u1); 1] - return v11 + v3 = make_array [Field 2, Field 3, Field 5, Field 5] : [(Field, Field); 2] + v7 = make_array [Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0] : [(Field, Field, u1); 2] + v10 = make_array [Field 1478523918288173385110236399861791147958001875200066088686689589556927843200, Field 700144278551281040379388961242974992655630750193306467120985766322057145630, u1 0] : [(Field, Field, u1); 1] + return v10 } "); } @@ -391,10 +397,10 @@ mod multi_scalar_mul { let src = r#" acir(inline) fn main f0 { b0(v0: Field, v1: Field): - v2 = make_array [v0, Field 0, Field 0, Field 0, v0, Field 0] : [Field; 6] + v2 = make_array [v0, Field 0, Field 0, Field 0, v0, Field 0] : [(Field, Field); 3] v3 = make_array [ - Field 0, Field 0, Field 1, v0, v1, Field 0, Field 1, v0, Field 0] : [Field; 9] - v4 = call multi_scalar_mul (v3, v2) -> [Field; 3] + Field 0, Field 0, u1 1, v0, v1, u1 0, Field 1, v0, u1 0] : [(Field, Field, u1); 3] + v4 = call multi_scalar_mul (v3, v2) -> [(Field, Field, u1); 1] return v4 @@ -404,12 +410,12 @@ mod multi_scalar_mul { assert_ssa_snapshot!(ssa, @r" acir(inline) fn main f0 { b0(v0: Field, v1: Field): - v3 = make_array [v0, Field 0, Field 0, Field 0, v0, Field 0] : [Field; 6] - v5 = make_array [Field 0, Field 0, Field 1, v0, v1, Field 0, Field 1, v0, Field 0] : [Field; 9] - v6 = make_array [v0, Field 0] : [Field; 2] - v7 = make_array [Field 1, v0, Field 0] : [Field; 3] - v9 = call multi_scalar_mul(v7, v6) -> [Field; 3] - return v9 + v3 = make_array [v0, Field 0, Field 0, Field 0, v0, Field 0] : [(Field, Field); 3] + v7 = make_array [Field 0, Field 0, u1 1, v0, v1, u1 0, Field 1, v0, u1 0] : [(Field, Field, u1); 3] + v8 = make_array [v0, Field 0] : [(Field, Field); 1] + v9 = make_array [Field 1, v0, u1 0] : [(Field, Field, u1); 1] + v11 = call multi_scalar_mul(v9, v8) -> [(Field, Field, u1); 1] + return v11 } "); } @@ -420,10 +426,10 @@ mod multi_scalar_mul { let src = r#" acir(inline) fn main f0 { b0(v0: Field, v1: Field): - v2 = make_array [Field 1, Field 0, v0, Field 0, Field 2, Field 0] : [Field; 6] + v2 = make_array [Field 1, Field 0, v0, Field 0, Field 2, Field 0] : [(Field, Field); 3] v3 = make_array [ - Field 1, Field 17631683881184975370165255887551781615748388533673675138860, Field 0, v0, v1, Field 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, Field 0] : [Field; 9] - v4 = call multi_scalar_mul (v3, v2) -> [Field; 3] + Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0, v0, v1, u1 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0] : [(Field, Field, u1); 3] + v4 = call multi_scalar_mul (v3, v2) -> [(Field, Field, u1); 1] return v4 }"#; let ssa = Ssa::from_str_simplifying(src).unwrap(); @@ -431,11 +437,11 @@ mod multi_scalar_mul { assert_ssa_snapshot!(ssa, @r" acir(inline) fn main f0 { b0(v0: Field, v1: Field): - v5 = make_array [Field 1, Field 0, v0, Field 0, Field 2, Field 0] : [Field; 6] - v7 = make_array [Field 1, Field 17631683881184975370165255887551781615748388533673675138860, Field 0, v0, v1, Field 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, Field 0] : [Field; 9] - v8 = make_array [v0, Field 0, Field 1, Field 0] : [Field; 4] - v12 = make_array [v0, v1, Field 0, Field -3227352362257037263902424173275354266044964400219754872043023745437788450996, Field 8902249110305491597038405103722863701255802573786510474664632793109847672620, u1 0] : [Field; 6] - v14 = call multi_scalar_mul(v12, v8) -> [Field; 3] + v5 = make_array [Field 1, Field 0, v0, Field 0, Field 2, Field 0] : [(Field, Field); 3] + v8 = make_array [Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0, v0, v1, u1 0, Field 1, Field 17631683881184975370165255887551781615748388533673675138860, u1 0] : [(Field, Field, u1); 3] + v9 = make_array [v0, Field 0, Field 1, Field 0] : [(Field, Field); 2] + v12 = make_array [v0, v1, u1 0, Field -3227352362257037263902424173275354266044964400219754872043023745437788450996, Field 8902249110305491597038405103722863701255802573786510474664632793109847672620, u1 0] : [(Field, Field, u1); 2] + v14 = call multi_scalar_mul(v12, v9) -> [(Field, Field, u1); 1] return v14 } "); diff --git a/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs b/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs index e2dff51f5dd..bdf45eb19c1 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -1511,7 +1511,7 @@ mod test { } brillig(inline) fn one f1 { - b0(v0: Field, v1: i32, v2: i32, v3: Field): + b0(v0: Field, v1: i32, v2: Field, v3: i32): v4 = make_array [v0, v1, v2, v3] : [(Field, i32); 2] return v4 } diff --git a/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs b/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs index 9af9f43cdf0..ca816bb27d0 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs @@ -1440,7 +1440,7 @@ mod tests { let src = r#" acir(inline) fn main f0 { b0(v0: u32): - v1 = make_array [f1] : [function; 0] + v1 = make_array [f1] : [function; 1] v2 = array_set v1, index u32 0, value f2 return v0 } diff --git a/compiler/noirc_evaluator/src/ssa/validation/mod.rs b/compiler/noirc_evaluator/src/ssa/validation/mod.rs index ee411ca7acc..313af74b5b6 100644 --- a/compiler/noirc_evaluator/src/ssa/validation/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/validation/mod.rs @@ -12,6 +12,8 @@ //! - Check that the input values of certain instructions matches that instruction's constraint //! At the moment, only [Instruction::Binary], [Instruction::ArrayGet], and [Instruction::ArraySet] //! are type checked. +use core::panic; + use acvm::{AcirField, FieldElement}; use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; @@ -258,6 +260,51 @@ impl<'f> Validator<'f> { ); } } + Instruction::MakeArray { elements, typ: _ } => { + let results = dfg.instruction_results(instruction); + assert_eq!(results.len(), 1, "MakeArray must return exactly one value"); + + let result_type = dfg.type_of_value(results[0]); + + let composite_type = match result_type { + Type::Array(composite_type, length) => { + let array_flattened_length = composite_type.len() * length as usize; + if elements.len() != array_flattened_length { + panic!( + "MakeArray returns an array of flattened length {}, but it has {} elements", + array_flattened_length, + elements.len() + ); + } + composite_type + } + Type::Slice(composite_type) => { + if elements.len() % composite_type.len() != 0 { + panic!( + "MakeArray slice has {} elements but composite type has {} types which don't divide the number of elements", + elements.len(), + composite_type.len() + ); + } + composite_type + } + _ => { + panic!("MakeArray must return an array or slice type, not {result_type}"); + } + }; + + let composite_type_len = composite_type.len(); + for (index, element) in elements.iter().enumerate() { + let element_type = dfg.type_of_value(*element); + let expected_type = &composite_type[index % composite_type_len]; + if &element_type != expected_type { + panic!( + "MakeArray has incorrect element type at index {index}: expected {}, got {}", + expected_type, element_type + ); + } + } + } _ => (), } } @@ -603,4 +650,64 @@ mod tests { "; let _ = Ssa::from_str(src).unwrap(); } + + #[test] + #[should_panic( + expected = "MakeArray returns an array of flattened length 2, but it has 3 elements" + )] + fn make_array_returns_incorrect_length() { + let src = " + acir(inline) fn main f0 { + b0(): + v0 = make_array [u8 1, u8 2, u8 3] : [u8; 2] + return v0 + } + "; + let _ = Ssa::from_str(src).unwrap(); + } + + #[test] + #[should_panic( + expected = "MakeArray returns an array of flattened length 4, but it has 3 elements" + )] + fn make_array_returns_incorrect_length_composite_type() { + let src = " + acir(inline) fn main f0 { + b0(): + v0 = make_array [u8 1, u8 2, u8 3] : [(u8, u8); 2] + return v0 + } + "; + let _ = Ssa::from_str(src).unwrap(); + } + + #[test] + #[should_panic( + expected = "MakeArray slice has 3 elements but composite type has 2 types which don't divide the number of elements" + )] + fn make_array_slice_returns_incorrect_length() { + let src = " + acir(inline) fn main f0 { + b0(): + v0 = make_array [u8 1, u8 2, u8 3] : [(u8, u8)] + return v0 + } + "; + let _ = Ssa::from_str(src).unwrap(); + } + + #[test] + #[should_panic( + expected = "MakeArray has incorrect element type at index 1: expected u8, got Field" + )] + fn make_array_has_incorrect_element_type() { + let src = " + acir(inline) fn main f0 { + b0(): + v0 = make_array [u8 1, Field 2, u8 3, u8 4] : [(u8, u8); 2] + return v0 + } + "; + let _ = Ssa::from_str(src).unwrap(); + } } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_-9223372036854775808.snap b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_-9223372036854775808.snap index a134c1bd4f7..f855816f6bd 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_-9223372036854775808.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_-9223372036854775808.snap @@ -34,7 +34,7 @@ expression: artifact }, "bytecode": [ "func 0", - "current witness index : _63", + "current witness index : _15", "private parameters indices : [_0]", "public parameters indices : [_1, _2]", "return value indices : []", @@ -48,51 +48,11 @@ expression: artifact "EXPR [ (-1, _10) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", "BLACKBOX::MULTI_SCALAR_MUL [(1, 254), (17631683881184975370165255887551781615748388533673675138860, 254), (0, 1), (_1, 254), (_2, 254), (0, 1), (11179562631109628533987091031692370366552561688588090155835439555627259799605, 254), (3443719903172018228650470536370404288991794296383447657609081676265727805364, 254), (0, 1), (_0, 254), (0, 254), (_0, 254), (0, 254), (1, 254), (0, 254)] [_13, _14, _15]", "EXPR [ (1, _13) 7349266043899242844836273743257843180744506495159104166319746739537754653274 ]", - "BLACKBOX::MULTI_SCALAR_MUL [(1, 254), (17631683881184975370165255887551781615748388533673675138860, 254), (0, 1), (_0, 254), (0, 254)] [_16, _17, _18]", - "EXPR [ (1, _18) 0 ]", - "EXPR [ (1, _16) -1 ]", - "EXPR [ (1, _17) -17631683881184975370165255887551781615748388533673675138860 ]", - "EXPR [ (1, _1) (-1, _2) (-1, _19) 0 ]", - "BRILLIG CALL func 0: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(19))], q_c: 0 })], outputs: [Simple(Witness(20))]", - "EXPR [ (1, _19, _20) (1, _21) -1 ]", - "EXPR [ (1, _19, _21) 0 ]", - "EXPR [ (-17631683881184975370165255887551781615748388533673675138858, _21) (-1, _22) 17631683881184975370165255887551781615748388533673675138860 ]", - "EXPR [ (-1, _23) 1 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_23, 254), (_22, 254), (_6, 1), (_23, 254), (_22, 254), (_6, 1)] [_24, _25, _26]", - "EXPR [ (1, _21, _24) (-1, _21) 0 ]", - "EXPR [ (-3078034153852398078128400807926804309327113743808504829582559963737223069693, _21) (-1, _27) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "EXPR [ (9191351987198133172789796342745422989482268917117950487758512501574271532888, _21) (-1, _28) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_23, 254), (_22, 254), (_6, 1), (_27, 254), (_28, 254), (_6, 1)] [_29, _30, _31]", - "EXPR [ (1, _21, _29) (-1, _21) 0 ]", - "EXPR [ (1, _1, _21) (-1, _32) 1 ]", - "EXPR [ (1, _2, _21) (-17631683881184975370165255887551781615748388533673675138860, _21) (-1, _33) 17631683881184975370165255887551781615748388533673675138860 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_32, 254), (_33, 254), (_6, 1), (_32, 254), (_33, 254), (_6, 1)] [_34, _35, _36]", - "EXPR [ (1, _21, _34) (-1, _21) 0 ]", - "EXPR [ (1, _1, _21) (-3078034153852398078128400807926804309327113743808504829582559963737223069693, _21) (-1, _37) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "EXPR [ (1, _2, _21) (9191351987198133172789796342745422989482268917117950487758512501574271532886, _21) (-1, _38) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_32, 254), (_33, 254), (_6, 1), (_37, 254), (_38, 254), (_6, 1)] [_39, _40, _41]", - "EXPR [ (1, _21, _39) (-1, _21) 0 ]", - "EXPR [ (1, _21) (-1, _42) 1 ]", - "EXPR [ (-17631683881184975370165255887551781615748388533673675138857, _21) (-1, _43) 17631683881184975370165255887551781615748388533673675138860 ]", - "EXPR [ (1, _1, _21) (-3078034153852398078128400807926804309327113743808504829582559963737223069694, _21) (-1, _44) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_42, 254), (_43, 254), (_6, 1), (_44, 254), (_38, 254), (_6, 1)] [_45, _46, _47]", - "EXPR [ (1, _21, _45) (-1, _21) 0 ]", - "EXPR [ (-3078034153852398078128400807926804309327113743808504829582559963737223069692, _21) (-1, _48) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "EXPR [ (9191351987198133172789796342745422989482268917117950487758512501574271532889, _21) (-1, _49) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_42, 254), (_43, 254), (_6, 1), (_48, 254), (_49, 254), (_6, 1)] [_50, _51, _52]", - "EXPR [ (1, _21, _50) (-1, _21) 0 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_42, 254), (_43, 254), (_6, 1), (_42, 254), (_43, 254), (_6, 1)] [_53, _54, _55]", - "EXPR [ (1, _21, _53) (-1, _21) 0 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_23, 254), (_43, 254), (_6, 1), (_23, 254), (_43, 254), (_6, 1)] [_56, _57, _58]", - "EXPR [ (1, _21, _56) (-1, _21) 0 ]", - "EXPR [ (1, _1, _21) (-1, _21) (-1, _59) 1 ]", - "EXPR [ (9191351987198133172789796342745422989482268917117950487758512501574271532887, _21) (-1, _60) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_59, 254), (_43, 254), (_6, 1), (_44, 254), (_60, 254), (_6, 1)] [_61, _62, _63]", - "EXPR [ (1, _21, _61) (-1, _21) 0 ]", - "unconstrained func 0", - "[Const { destination: Direct(21), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(20), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(0), size_address: Direct(21), offset_address: Direct(20) }, Const { destination: Direct(2), bit_size: Field, value: 0 }, BinaryFieldOp { destination: Direct(3), op: Equals, lhs: Direct(0), rhs: Direct(2) }, JumpIf { condition: Direct(3), location: 8 }, Const { destination: Direct(1), bit_size: Field, value: 1 }, BinaryFieldOp { destination: Direct(0), op: Div, lhs: Direct(1), rhs: Direct(0) }, Stop { return_data: HeapVector { pointer: Direct(20), size: Direct(21) } }]" + "EXPR [ (1, _5) 0 ]", + "EXPR [ (1, _1) -1 ]", + "EXPR [ (1, _2) -17631683881184975370165255887551781615748388533673675138860 ]" ], - "debug_symbols": "tVjLbuowEP0Xr7PwvPzor1xdVZSmFVIEKIUrXVX9946LndCFUWuS1QGSOcwce04yfjfP/dP59XG3fzm8mYc/7+Zp3A3D7vVxOGw3p91hr7++f3SmfH08jX2vP5mr6xp13Iz9/mQe9udh6My/zXD+uuntuNl/4Wkz6lXbmX7/rKiEL7uhT58+ujna1kMxSA7G4KZw+XE8ecjxjKEWj/V4lsiFwPFcALg2Bqox3KiBeapBpEEDdrHEB2qId7GsgQeoxfsb8VjydwK1+kM93qNgSQAjNTAEsiWFQIw1BrghAgBanzn0s/ASJL5hN3hxRQzfsprBFSki2Vo88N0t8XOKlp4Ay1SEtM426ADkJwahqpIQ7lcirKqEcNkQ4DC2KBF8yQFi5KpLLmCTq/ok2qm50CI3KIHan4UBqImBpFSB5Kq7Cu+1S7zldnbyy2Bj1WMwLuB2eL/rEiyQx29IWlwXKeC0rlea/mJncPKBCwNL9TlKsoQasrIa7OZafGhRw/PUaZ5bXAsDTN0esPpuyPbOTmO4u9MYF1jTm3n8rNOYl8iDV95bga9e+W3TzghFDYxQdXEOS6gRVlYj0lwLQ8sEhFjecwil2ieyxB79DUmLGoR+rqVpliGOZRgiIayq4ZZQw62shvBci7R4KHlfeo2Crfq4W2IucivPRfqAnmuhpjnZSnkmsa3vLreEi7qVXZTBTrUAtLgoE5VeY3JV33BLuKhb2UVZd8RUS/y+sn/122a7G7+dfBmru6gzoLd0BjXBzlD6+87wBSQNkJ1xaf7qjFfQHEMaoDoT0/SgwTa9KyoqS9qagBkpo1KhEoNkdBl9xpBcTjFeEG1GSDamqHyk9yFl5IySOkDRpaFK0WcMGZWPNVtSvmQgBBkxo/KJ5k/KJ5o/SUaX0WdUPlE+Uj5RPrYZIaPyifKx8qUzB1Y+p3Es6X1LUflcus+nIybFkDFeUGw6cPpIqzruNk9Dn48kX8777dUJ5en/sVwpZ5jH8bDtn89jn9b065qu8ic=", + "debug_symbols": "tVXbbsIwDP2XPOchce78yjShUgKqFLVVaCdNiH+fw5rCHoJQGE9u4p4j+zi2z2Tvd/Nx2/WH4UQ2H2eyi10I3XEbhraZuqHH2/OFknzcTtF7vCJ3fkSNTfT9RDb9HAIlX02Yrz+dxqa/2qmJ6GWU+H6PFgkPXfDp60JvaFaGglULGKxe4eppvDB8wUuwJTyU8VI5mQm0vCXAdR2DKDE8yEHKNQelKjSQ2mW8FRV47XINDOclvHmAhxy/VryUvy3jrWCZwAoJJQZXZuAcmFko8FvJf+AwFZU0SmclTU0lrM5COMFKeC5efs7PU9S8Z86kyEIyzSp04MKsDEoUleTmdSXMW5VQMj8IrsHVKGFNjoE7J4sTjr8zDWBrZwADWZEGCJVjAKGLBQX54pQB9aC5mII8Zpgrtjfo2jnziaem7eKfHUsYLilKOOZKCWDwlIjUF5TIX6PQYFwaDWZvEhUlNlWeEpcERzBLsqHli4VkLynO2DW74Jdlfpj79m63T99j9uTtP8ah9fs5+hTj1YdR/wA=", "file_map": { "16": { "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the\n// underlying proof system.\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n let mut result = embedded_curve_add_unsafe(point1_1, point2_1);\n\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n let double = embedded_curve_add_unsafe(point1, point1);\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n result = if double_predicate { double } else { result };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n // Ensure is_infinite is comptime\n let point1_1 = EmbeddedCurvePoint { x: point1.x, y: point1.y, is_infinite: false };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n embedded_curve_add_unsafe(point1_1, point2_1)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2)[0]\n}\n", @@ -106,7 +66,5 @@ expression: artifact "names": [ "main" ], - "brillig_names": [ - "directive_invert" - ] + "brillig_names": [] } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_0.snap b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_0.snap index a134c1bd4f7..f855816f6bd 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_0.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_0.snap @@ -34,7 +34,7 @@ expression: artifact }, "bytecode": [ "func 0", - "current witness index : _63", + "current witness index : _15", "private parameters indices : [_0]", "public parameters indices : [_1, _2]", "return value indices : []", @@ -48,51 +48,11 @@ expression: artifact "EXPR [ (-1, _10) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", "BLACKBOX::MULTI_SCALAR_MUL [(1, 254), (17631683881184975370165255887551781615748388533673675138860, 254), (0, 1), (_1, 254), (_2, 254), (0, 1), (11179562631109628533987091031692370366552561688588090155835439555627259799605, 254), (3443719903172018228650470536370404288991794296383447657609081676265727805364, 254), (0, 1), (_0, 254), (0, 254), (_0, 254), (0, 254), (1, 254), (0, 254)] [_13, _14, _15]", "EXPR [ (1, _13) 7349266043899242844836273743257843180744506495159104166319746739537754653274 ]", - "BLACKBOX::MULTI_SCALAR_MUL [(1, 254), (17631683881184975370165255887551781615748388533673675138860, 254), (0, 1), (_0, 254), (0, 254)] [_16, _17, _18]", - "EXPR [ (1, _18) 0 ]", - "EXPR [ (1, _16) -1 ]", - "EXPR [ (1, _17) -17631683881184975370165255887551781615748388533673675138860 ]", - "EXPR [ (1, _1) (-1, _2) (-1, _19) 0 ]", - "BRILLIG CALL func 0: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(19))], q_c: 0 })], outputs: [Simple(Witness(20))]", - "EXPR [ (1, _19, _20) (1, _21) -1 ]", - "EXPR [ (1, _19, _21) 0 ]", - "EXPR [ (-17631683881184975370165255887551781615748388533673675138858, _21) (-1, _22) 17631683881184975370165255887551781615748388533673675138860 ]", - "EXPR [ (-1, _23) 1 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_23, 254), (_22, 254), (_6, 1), (_23, 254), (_22, 254), (_6, 1)] [_24, _25, _26]", - "EXPR [ (1, _21, _24) (-1, _21) 0 ]", - "EXPR [ (-3078034153852398078128400807926804309327113743808504829582559963737223069693, _21) (-1, _27) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "EXPR [ (9191351987198133172789796342745422989482268917117950487758512501574271532888, _21) (-1, _28) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_23, 254), (_22, 254), (_6, 1), (_27, 254), (_28, 254), (_6, 1)] [_29, _30, _31]", - "EXPR [ (1, _21, _29) (-1, _21) 0 ]", - "EXPR [ (1, _1, _21) (-1, _32) 1 ]", - "EXPR [ (1, _2, _21) (-17631683881184975370165255887551781615748388533673675138860, _21) (-1, _33) 17631683881184975370165255887551781615748388533673675138860 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_32, 254), (_33, 254), (_6, 1), (_32, 254), (_33, 254), (_6, 1)] [_34, _35, _36]", - "EXPR [ (1, _21, _34) (-1, _21) 0 ]", - "EXPR [ (1, _1, _21) (-3078034153852398078128400807926804309327113743808504829582559963737223069693, _21) (-1, _37) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "EXPR [ (1, _2, _21) (9191351987198133172789796342745422989482268917117950487758512501574271532886, _21) (-1, _38) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_32, 254), (_33, 254), (_6, 1), (_37, 254), (_38, 254), (_6, 1)] [_39, _40, _41]", - "EXPR [ (1, _21, _39) (-1, _21) 0 ]", - "EXPR [ (1, _21) (-1, _42) 1 ]", - "EXPR [ (-17631683881184975370165255887551781615748388533673675138857, _21) (-1, _43) 17631683881184975370165255887551781615748388533673675138860 ]", - "EXPR [ (1, _1, _21) (-3078034153852398078128400807926804309327113743808504829582559963737223069694, _21) (-1, _44) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_42, 254), (_43, 254), (_6, 1), (_44, 254), (_38, 254), (_6, 1)] [_45, _46, _47]", - "EXPR [ (1, _21, _45) (-1, _21) 0 ]", - "EXPR [ (-3078034153852398078128400807926804309327113743808504829582559963737223069692, _21) (-1, _48) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "EXPR [ (9191351987198133172789796342745422989482268917117950487758512501574271532889, _21) (-1, _49) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_42, 254), (_43, 254), (_6, 1), (_48, 254), (_49, 254), (_6, 1)] [_50, _51, _52]", - "EXPR [ (1, _21, _50) (-1, _21) 0 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_42, 254), (_43, 254), (_6, 1), (_42, 254), (_43, 254), (_6, 1)] [_53, _54, _55]", - "EXPR [ (1, _21, _53) (-1, _21) 0 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_23, 254), (_43, 254), (_6, 1), (_23, 254), (_43, 254), (_6, 1)] [_56, _57, _58]", - "EXPR [ (1, _21, _56) (-1, _21) 0 ]", - "EXPR [ (1, _1, _21) (-1, _21) (-1, _59) 1 ]", - "EXPR [ (9191351987198133172789796342745422989482268917117950487758512501574271532887, _21) (-1, _60) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_59, 254), (_43, 254), (_6, 1), (_44, 254), (_60, 254), (_6, 1)] [_61, _62, _63]", - "EXPR [ (1, _21, _61) (-1, _21) 0 ]", - "unconstrained func 0", - "[Const { destination: Direct(21), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(20), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(0), size_address: Direct(21), offset_address: Direct(20) }, Const { destination: Direct(2), bit_size: Field, value: 0 }, BinaryFieldOp { destination: Direct(3), op: Equals, lhs: Direct(0), rhs: Direct(2) }, JumpIf { condition: Direct(3), location: 8 }, Const { destination: Direct(1), bit_size: Field, value: 1 }, BinaryFieldOp { destination: Direct(0), op: Div, lhs: Direct(1), rhs: Direct(0) }, Stop { return_data: HeapVector { pointer: Direct(20), size: Direct(21) } }]" + "EXPR [ (1, _5) 0 ]", + "EXPR [ (1, _1) -1 ]", + "EXPR [ (1, _2) -17631683881184975370165255887551781615748388533673675138860 ]" ], - "debug_symbols": "tVjLbuowEP0Xr7PwvPzor1xdVZSmFVIEKIUrXVX9946LndCFUWuS1QGSOcwce04yfjfP/dP59XG3fzm8mYc/7+Zp3A3D7vVxOGw3p91hr7++f3SmfH08jX2vP5mr6xp13Iz9/mQe9udh6My/zXD+uuntuNl/4Wkz6lXbmX7/rKiEL7uhT58+ujna1kMxSA7G4KZw+XE8ecjxjKEWj/V4lsiFwPFcALg2Bqox3KiBeapBpEEDdrHEB2qId7GsgQeoxfsb8VjydwK1+kM93qNgSQAjNTAEsiWFQIw1BrghAgBanzn0s/ASJL5hN3hxRQzfsprBFSki2Vo88N0t8XOKlp4Ay1SEtM426ADkJwahqpIQ7lcirKqEcNkQ4DC2KBF8yQFi5KpLLmCTq/ok2qm50CI3KIHan4UBqImBpFSB5Kq7Cu+1S7zldnbyy2Bj1WMwLuB2eL/rEiyQx29IWlwXKeC0rlea/mJncPKBCwNL9TlKsoQasrIa7OZafGhRw/PUaZ5bXAsDTN0esPpuyPbOTmO4u9MYF1jTm3n8rNOYl8iDV95bga9e+W3TzghFDYxQdXEOS6gRVlYj0lwLQ8sEhFjecwil2ieyxB79DUmLGoR+rqVpliGOZRgiIayq4ZZQw62shvBci7R4KHlfeo2Crfq4W2IucivPRfqAnmuhpjnZSnkmsa3vLreEi7qVXZTBTrUAtLgoE5VeY3JV33BLuKhb2UVZd8RUS/y+sn/122a7G7+dfBmru6gzoLd0BjXBzlD6+87wBSQNkJ1xaf7qjFfQHEMaoDoT0/SgwTa9KyoqS9qagBkpo1KhEoNkdBl9xpBcTjFeEG1GSDamqHyk9yFl5IySOkDRpaFK0WcMGZWPNVtSvmQgBBkxo/KJ5k/KJ5o/SUaX0WdUPlE+Uj5RPrYZIaPyifKx8qUzB1Y+p3Es6X1LUflcus+nIybFkDFeUGw6cPpIqzruNk9Dn48kX8777dUJ5en/sVwpZ5jH8bDtn89jn9b065qu8ic=", + "debug_symbols": "tVXbbsIwDP2XPOchce78yjShUgKqFLVVaCdNiH+fw5rCHoJQGE9u4p4j+zi2z2Tvd/Nx2/WH4UQ2H2eyi10I3XEbhraZuqHH2/OFknzcTtF7vCJ3fkSNTfT9RDb9HAIlX02Yrz+dxqa/2qmJ6GWU+H6PFgkPXfDp60JvaFaGglULGKxe4eppvDB8wUuwJTyU8VI5mQm0vCXAdR2DKDE8yEHKNQelKjSQ2mW8FRV47XINDOclvHmAhxy/VryUvy3jrWCZwAoJJQZXZuAcmFko8FvJf+AwFZU0SmclTU0lrM5COMFKeC5efs7PU9S8Z86kyEIyzSp04MKsDEoUleTmdSXMW5VQMj8IrsHVKGFNjoE7J4sTjr8zDWBrZwADWZEGCJVjAKGLBQX54pQB9aC5mII8Zpgrtjfo2jnziaem7eKfHUsYLilKOOZKCWDwlIjUF5TIX6PQYFwaDWZvEhUlNlWeEpcERzBLsqHli4VkLynO2DW74Jdlfpj79m63T99j9uTtP8ah9fs5+hTj1YdR/wA=", "file_map": { "16": { "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the\n// underlying proof system.\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n let mut result = embedded_curve_add_unsafe(point1_1, point2_1);\n\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n let double = embedded_curve_add_unsafe(point1, point1);\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n result = if double_predicate { double } else { result };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n // Ensure is_infinite is comptime\n let point1_1 = EmbeddedCurvePoint { x: point1.x, y: point1.y, is_infinite: false };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n embedded_curve_add_unsafe(point1_1, point2_1)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2)[0]\n}\n", @@ -106,7 +66,5 @@ expression: artifact "names": [ "main" ], - "brillig_names": [ - "directive_invert" - ] + "brillig_names": [] } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_9223372036854775807.snap b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_9223372036854775807.snap index a134c1bd4f7..f855816f6bd 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_9223372036854775807.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_false_inliner_9223372036854775807.snap @@ -34,7 +34,7 @@ expression: artifact }, "bytecode": [ "func 0", - "current witness index : _63", + "current witness index : _15", "private parameters indices : [_0]", "public parameters indices : [_1, _2]", "return value indices : []", @@ -48,51 +48,11 @@ expression: artifact "EXPR [ (-1, _10) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", "BLACKBOX::MULTI_SCALAR_MUL [(1, 254), (17631683881184975370165255887551781615748388533673675138860, 254), (0, 1), (_1, 254), (_2, 254), (0, 1), (11179562631109628533987091031692370366552561688588090155835439555627259799605, 254), (3443719903172018228650470536370404288991794296383447657609081676265727805364, 254), (0, 1), (_0, 254), (0, 254), (_0, 254), (0, 254), (1, 254), (0, 254)] [_13, _14, _15]", "EXPR [ (1, _13) 7349266043899242844836273743257843180744506495159104166319746739537754653274 ]", - "BLACKBOX::MULTI_SCALAR_MUL [(1, 254), (17631683881184975370165255887551781615748388533673675138860, 254), (0, 1), (_0, 254), (0, 254)] [_16, _17, _18]", - "EXPR [ (1, _18) 0 ]", - "EXPR [ (1, _16) -1 ]", - "EXPR [ (1, _17) -17631683881184975370165255887551781615748388533673675138860 ]", - "EXPR [ (1, _1) (-1, _2) (-1, _19) 0 ]", - "BRILLIG CALL func 0: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(19))], q_c: 0 })], outputs: [Simple(Witness(20))]", - "EXPR [ (1, _19, _20) (1, _21) -1 ]", - "EXPR [ (1, _19, _21) 0 ]", - "EXPR [ (-17631683881184975370165255887551781615748388533673675138858, _21) (-1, _22) 17631683881184975370165255887551781615748388533673675138860 ]", - "EXPR [ (-1, _23) 1 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_23, 254), (_22, 254), (_6, 1), (_23, 254), (_22, 254), (_6, 1)] [_24, _25, _26]", - "EXPR [ (1, _21, _24) (-1, _21) 0 ]", - "EXPR [ (-3078034153852398078128400807926804309327113743808504829582559963737223069693, _21) (-1, _27) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "EXPR [ (9191351987198133172789796342745422989482268917117950487758512501574271532888, _21) (-1, _28) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_23, 254), (_22, 254), (_6, 1), (_27, 254), (_28, 254), (_6, 1)] [_29, _30, _31]", - "EXPR [ (1, _21, _29) (-1, _21) 0 ]", - "EXPR [ (1, _1, _21) (-1, _32) 1 ]", - "EXPR [ (1, _2, _21) (-17631683881184975370165255887551781615748388533673675138860, _21) (-1, _33) 17631683881184975370165255887551781615748388533673675138860 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_32, 254), (_33, 254), (_6, 1), (_32, 254), (_33, 254), (_6, 1)] [_34, _35, _36]", - "EXPR [ (1, _21, _34) (-1, _21) 0 ]", - "EXPR [ (1, _1, _21) (-3078034153852398078128400807926804309327113743808504829582559963737223069693, _21) (-1, _37) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "EXPR [ (1, _2, _21) (9191351987198133172789796342745422989482268917117950487758512501574271532886, _21) (-1, _38) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_32, 254), (_33, 254), (_6, 1), (_37, 254), (_38, 254), (_6, 1)] [_39, _40, _41]", - "EXPR [ (1, _21, _39) (-1, _21) 0 ]", - "EXPR [ (1, _21) (-1, _42) 1 ]", - "EXPR [ (-17631683881184975370165255887551781615748388533673675138857, _21) (-1, _43) 17631683881184975370165255887551781615748388533673675138860 ]", - "EXPR [ (1, _1, _21) (-3078034153852398078128400807926804309327113743808504829582559963737223069694, _21) (-1, _44) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_42, 254), (_43, 254), (_6, 1), (_44, 254), (_38, 254), (_6, 1)] [_45, _46, _47]", - "EXPR [ (1, _21, _45) (-1, _21) 0 ]", - "EXPR [ (-3078034153852398078128400807926804309327113743808504829582559963737223069692, _21) (-1, _48) 3078034153852398078128400807926804309327113743808504829582559963737223069694 ]", - "EXPR [ (9191351987198133172789796342745422989482268917117950487758512501574271532889, _21) (-1, _49) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_42, 254), (_43, 254), (_6, 1), (_48, 254), (_49, 254), (_6, 1)] [_50, _51, _52]", - "EXPR [ (1, _21, _50) (-1, _21) 0 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_42, 254), (_43, 254), (_6, 1), (_42, 254), (_43, 254), (_6, 1)] [_53, _54, _55]", - "EXPR [ (1, _21, _53) (-1, _21) 0 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_23, 254), (_43, 254), (_6, 1), (_23, 254), (_43, 254), (_6, 1)] [_56, _57, _58]", - "EXPR [ (1, _21, _56) (-1, _21) 0 ]", - "EXPR [ (1, _1, _21) (-1, _21) (-1, _59) 1 ]", - "EXPR [ (9191351987198133172789796342745422989482268917117950487758512501574271532887, _21) (-1, _60) -9191351987198133172789796342745422989482268917117950487758512501574271532885 ]", - "BLACKBOX::EMBEDDED_CURVE_ADD [(_59, 254), (_43, 254), (_6, 1), (_44, 254), (_60, 254), (_6, 1)] [_61, _62, _63]", - "EXPR [ (1, _21, _61) (-1, _21) 0 ]", - "unconstrained func 0", - "[Const { destination: Direct(21), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(20), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(0), size_address: Direct(21), offset_address: Direct(20) }, Const { destination: Direct(2), bit_size: Field, value: 0 }, BinaryFieldOp { destination: Direct(3), op: Equals, lhs: Direct(0), rhs: Direct(2) }, JumpIf { condition: Direct(3), location: 8 }, Const { destination: Direct(1), bit_size: Field, value: 1 }, BinaryFieldOp { destination: Direct(0), op: Div, lhs: Direct(1), rhs: Direct(0) }, Stop { return_data: HeapVector { pointer: Direct(20), size: Direct(21) } }]" + "EXPR [ (1, _5) 0 ]", + "EXPR [ (1, _1) -1 ]", + "EXPR [ (1, _2) -17631683881184975370165255887551781615748388533673675138860 ]" ], - "debug_symbols": "tVjLbuowEP0Xr7PwvPzor1xdVZSmFVIEKIUrXVX9946LndCFUWuS1QGSOcwce04yfjfP/dP59XG3fzm8mYc/7+Zp3A3D7vVxOGw3p91hr7++f3SmfH08jX2vP5mr6xp13Iz9/mQe9udh6My/zXD+uuntuNl/4Wkz6lXbmX7/rKiEL7uhT58+ujna1kMxSA7G4KZw+XE8ecjxjKEWj/V4lsiFwPFcALg2Bqox3KiBeapBpEEDdrHEB2qId7GsgQeoxfsb8VjydwK1+kM93qNgSQAjNTAEsiWFQIw1BrghAgBanzn0s/ASJL5hN3hxRQzfsprBFSki2Vo88N0t8XOKlp4Ay1SEtM426ADkJwahqpIQ7lcirKqEcNkQ4DC2KBF8yQFi5KpLLmCTq/ok2qm50CI3KIHan4UBqImBpFSB5Kq7Cu+1S7zldnbyy2Bj1WMwLuB2eL/rEiyQx29IWlwXKeC0rlea/mJncPKBCwNL9TlKsoQasrIa7OZafGhRw/PUaZ5bXAsDTN0esPpuyPbOTmO4u9MYF1jTm3n8rNOYl8iDV95bga9e+W3TzghFDYxQdXEOS6gRVlYj0lwLQ8sEhFjecwil2ieyxB79DUmLGoR+rqVpliGOZRgiIayq4ZZQw62shvBci7R4KHlfeo2Crfq4W2IucivPRfqAnmuhpjnZSnkmsa3vLreEi7qVXZTBTrUAtLgoE5VeY3JV33BLuKhb2UVZd8RUS/y+sn/122a7G7+dfBmru6gzoLd0BjXBzlD6+87wBSQNkJ1xaf7qjFfQHEMaoDoT0/SgwTa9KyoqS9qagBkpo1KhEoNkdBl9xpBcTjFeEG1GSDamqHyk9yFl5IySOkDRpaFK0WcMGZWPNVtSvmQgBBkxo/KJ5k/KJ5o/SUaX0WdUPlE+Uj5RPrYZIaPyifKx8qUzB1Y+p3Es6X1LUflcus+nIybFkDFeUGw6cPpIqzruNk9Dn48kX8777dUJ5en/sVwpZ5jH8bDtn89jn9b065qu8ic=", + "debug_symbols": "tVXbbsIwDP2XPOchce78yjShUgKqFLVVaCdNiH+fw5rCHoJQGE9u4p4j+zi2z2Tvd/Nx2/WH4UQ2H2eyi10I3XEbhraZuqHH2/OFknzcTtF7vCJ3fkSNTfT9RDb9HAIlX02Yrz+dxqa/2qmJ6GWU+H6PFgkPXfDp60JvaFaGglULGKxe4eppvDB8wUuwJTyU8VI5mQm0vCXAdR2DKDE8yEHKNQelKjSQ2mW8FRV47XINDOclvHmAhxy/VryUvy3jrWCZwAoJJQZXZuAcmFko8FvJf+AwFZU0SmclTU0lrM5COMFKeC5efs7PU9S8Z86kyEIyzSp04MKsDEoUleTmdSXMW5VQMj8IrsHVKGFNjoE7J4sTjr8zDWBrZwADWZEGCJVjAKGLBQX54pQB9aC5mII8Zpgrtjfo2jnziaem7eKfHUsYLilKOOZKCWDwlIjUF5TIX6PQYFwaDWZvEhUlNlWeEpcERzBLsqHli4VkLynO2DW74Jdlfpj79m63T99j9uTtP8ah9fs5+hTj1YdR/wA=", "file_map": { "16": { "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the\n// underlying proof system.\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n let mut result = embedded_curve_add_unsafe(point1_1, point2_1);\n\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n let double = embedded_curve_add_unsafe(point1, point1);\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n result = if double_predicate { double } else { result };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n // Ensure is_infinite is comptime\n let point1_1 = EmbeddedCurvePoint { x: point1.x, y: point1.y, is_infinite: false };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n embedded_curve_add_unsafe(point1_1, point2_1)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2)[0]\n}\n", @@ -106,7 +66,5 @@ expression: artifact "names": [ "main" ], - "brillig_names": [ - "directive_invert" - ] + "brillig_names": [] } diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_-9223372036854775808.snap b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_-9223372036854775808.snap index 4e4ecc82ff4..ceda3db2de1 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_-9223372036854775808.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_-9223372036854775808.snap @@ -31,6 +31,10 @@ expression: artifact ], "return_type": null, "error_types": { + "12049594436772143978": { + "error_kind": "string", + "string": "array ref-count underflow detected" + }, "17843811134343075018": { "error_kind": "string", "string": "Stack too deep" @@ -45,9 +49,9 @@ expression: artifact "return value indices : []", "BRILLIG CALL func 0: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(1))], q_c: 0 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })], outputs: []", "unconstrained func 0", - "[Const { destination: Direct(2), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(1), bit_size: Integer(U32), value: 32841 }, Const { destination: Direct(0), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(4), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(5), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(32838), size_address: Relative(4), offset_address: Relative(5) }, Mov { destination: Relative(1), source: Direct(32838) }, Mov { destination: Relative(2), source: Direct(32839) }, Mov { destination: Relative(3), source: Direct(32840) }, Call { location: 14 }, Call { location: 18 }, Const { destination: Relative(1), bit_size: Integer(U32), value: 32841 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Stop { return_data: HeapVector { pointer: Relative(1), size: Relative(2) } }, Const { destination: Direct(32835), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(32836), bit_size: Integer(U32), value: 2 }, Const { destination: Direct(32837), bit_size: Integer(U32), value: 3 }, Return, Call { location: 391 }, Const { destination: Relative(4), bit_size: Field, value: 1 }, Const { destination: Relative(5), bit_size: Field, value: 17631683881184975370165255887551781615748388533673675138860 }, Const { destination: Relative(6), bit_size: Integer(U1), value: 0 }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Mov { destination: Relative(9), source: Relative(8) }, Store { destination_pointer: Relative(9), source: Relative(4) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(5) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(6) }, Const { destination: Relative(8), bit_size: Field, value: 0 }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Mov { destination: Relative(11), source: Relative(10) }, Store { destination_pointer: Relative(11), source: Relative(1) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Store { destination_pointer: Relative(11), source: Relative(8) }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(11), size: Relative(12) }, scalars: HeapVector { pointer: Relative(13), size: Relative(14) }, outputs: HeapArray { pointer: Relative(15), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(32835) }, Load { destination: Relative(7), source_pointer: Relative(9) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(32836) }, Load { destination: Relative(9), source_pointer: Relative(11) }, BinaryFieldOp { destination: Relative(10), op: Equals, lhs: Relative(7), rhs: Relative(2) }, JumpIf { condition: Relative(10), location: 61 }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(11) } }, BinaryFieldOp { destination: Relative(7), op: Equals, lhs: Relative(9), rhs: Relative(3) }, JumpIf { condition: Relative(7), location: 65 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Const { destination: Relative(11), bit_size: Integer(U32), value: 12 }, Mov { destination: Relative(12), source: Direct(0) }, Mov { destination: Relative(13), source: Relative(2) }, Mov { destination: Relative(14), source: Relative(3) }, Mov { destination: Relative(15), source: Relative(6) }, Mov { destination: Relative(16), source: Relative(2) }, Mov { destination: Relative(17), source: Relative(3) }, Mov { destination: Relative(18), source: Relative(6) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(11) }, Call { location: 397 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(7), source: Relative(13) }, Mov { destination: Relative(9), source: Relative(14) }, Mov { destination: Relative(10), source: Relative(15) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 15 }, Mov { destination: Relative(15), source: Direct(0) }, Mov { destination: Relative(16), source: Relative(4) }, Mov { destination: Relative(17), source: Relative(5) }, Mov { destination: Relative(18), source: Relative(6) }, Mov { destination: Relative(19), source: Relative(4) }, Mov { destination: Relative(20), source: Relative(5) }, Mov { destination: Relative(21), source: Relative(6) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(14) }, Call { location: 397 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(11), source: Relative(16) }, Mov { destination: Relative(12), source: Relative(17) }, Mov { destination: Relative(13), source: Relative(18) }, BinaryFieldOp { destination: Relative(14), op: Equals, lhs: Relative(11), rhs: Relative(7) }, JumpIf { condition: Relative(14), location: 97 }, Const { destination: Relative(15), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(15) } }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 7 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Mov { destination: Relative(15), source: Relative(14) }, Store { destination_pointer: Relative(15), source: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(5) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(5) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, Mov { destination: Relative(14), source: Direct(1) }, Const { destination: Relative(15), bit_size: Integer(U32), value: 5 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(15) }, IndirectConst { destination_pointer: Relative(14), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Mov { destination: Relative(16), source: Relative(15) }, Store { destination_pointer: Relative(16), source: Relative(1) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(8) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(1) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(8) }, Mov { destination: Relative(15), source: Direct(1) }, Const { destination: Relative(16), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(16) }, IndirectConst { destination_pointer: Relative(15), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Const { destination: Relative(17), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Const { destination: Relative(19), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Relative(20), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(16), size: Relative(17) }, scalars: HeapVector { pointer: Relative(18), size: Relative(19) }, outputs: HeapArray { pointer: Relative(20), size: 3 } }), BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(32835) }, Load { destination: Relative(7), source_pointer: Relative(14) }, BinaryFieldOp { destination: Relative(14), op: Equals, lhs: Relative(11), rhs: Relative(7) }, JumpIf { condition: Relative(14), location: 143 }, Const { destination: Relative(15), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(15) } }, Const { destination: Relative(7), bit_size: Field, value: 23 }, Mov { destination: Relative(14), source: Direct(1) }, Const { destination: Relative(15), bit_size: Integer(U32), value: 9 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(15) }, IndirectConst { destination_pointer: Relative(14), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Mov { destination: Relative(16), source: Relative(15) }, Store { destination_pointer: Relative(16), source: Relative(1) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(8) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(7) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(8) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(1) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(8) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(4) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(8) }, Const { destination: Relative(7), bit_size: Field, value: 10456889356757736161582760391335869408742580538510966583040563008531594628700 }, Const { destination: Relative(15), bit_size: Field, value: 4714263418031017792755226781102360879566029698463912436805212494059649164343 }, Mov { destination: Relative(16), source: Direct(1) }, Const { destination: Relative(17), bit_size: Integer(U32), value: 13 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(17) }, IndirectConst { destination_pointer: Relative(16), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Mov { destination: Relative(18), source: Relative(17) }, Store { destination_pointer: Relative(18), source: Relative(4) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(5) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(6) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(11) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(12) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(13) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(2) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(3) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(6) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(7) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(15) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(6) }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 12 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Const { destination: Relative(15), bit_size: Integer(U32), value: 8 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(11), size: Relative(12) }, scalars: HeapVector { pointer: Relative(13), size: Relative(15) }, outputs: HeapArray { pointer: Relative(17), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(32835) }, Load { destination: Relative(11), source_pointer: Relative(12) }, Const { destination: Relative(7), bit_size: Field, value: -7349266043899242844836273743257843180744506495159104166319746739537754653274 }, BinaryFieldOp { destination: Relative(12), op: Equals, lhs: Relative(11), rhs: Relative(7) }, JumpIf { condition: Relative(12), location: 213 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Mov { destination: Relative(12), source: Relative(11) }, Store { destination_pointer: Relative(12), source: Relative(1) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(8) }, Mov { destination: Relative(1), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(1), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Mov { destination: Relative(11), source: Relative(8) }, Store { destination_pointer: Relative(11), source: Relative(4) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Store { destination_pointer: Relative(11), source: Relative(5) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Store { destination_pointer: Relative(11), source: Relative(6) }, Mov { destination: Relative(8), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(8), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(11), size: Relative(12) }, scalars: HeapVector { pointer: Relative(13), size: Relative(14) }, outputs: HeapArray { pointer: Relative(15), size: 3 } }), BinaryIntOp { destination: Relative(7), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(32835) }, Load { destination: Relative(1), source_pointer: Relative(7) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(32836) }, Load { destination: Relative(7), source_pointer: Relative(11) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(32837) }, Load { destination: Relative(11), source_pointer: Relative(12) }, BinaryIntOp { destination: Relative(8), op: Equals, bit_size: U1, lhs: Relative(11), rhs: Relative(6) }, JumpIf { condition: Relative(8), location: 253 }, Const { destination: Relative(12), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(12) } }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(1), rhs: Relative(4) }, JumpIf { condition: Relative(8), location: 257 }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(11) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(7), rhs: Relative(5) }, JumpIf { condition: Relative(1), location: 261 }, Const { destination: Relative(8), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(8) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(2), rhs: Relative(3) }, JumpIf { condition: Relative(1), location: 264 }, Jump { location: 390 }, Const { destination: Relative(1), bit_size: Field, value: 2 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 10 }, Mov { destination: Relative(10), source: Direct(0) }, Mov { destination: Relative(11), source: Relative(4) }, Mov { destination: Relative(12), source: Relative(1) }, Mov { destination: Relative(13), source: Relative(6) }, Mov { destination: Relative(14), source: Relative(4) }, Mov { destination: Relative(15), source: Relative(1) }, Mov { destination: Relative(16), source: Relative(6) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(9) }, Call { location: 397 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(5), source: Relative(11) }, Mov { destination: Relative(7), source: Relative(12) }, Mov { destination: Relative(8), source: Relative(13) }, BinaryFieldOp { destination: Relative(9), op: Equals, lhs: Relative(5), rhs: Relative(4) }, JumpIf { condition: Relative(9), location: 283 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Const { destination: Relative(5), bit_size: Field, value: 3 }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(4), input1_y: Relative(1), input1_infinite: Relative(6), input2_x: Relative(4), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(10), size: 3 } }), BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(32835) }, Load { destination: Relative(10), source_pointer: Relative(11) }, BinaryFieldOp { destination: Relative(9), op: Equals, lhs: Relative(10), rhs: Relative(4) }, JumpIf { condition: Relative(9), location: 296 }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(11) } }, BinaryFieldOp { destination: Relative(9), op: Add, lhs: Relative(2), rhs: Relative(4) }, BinaryFieldOp { destination: Relative(10), op: Add, lhs: Relative(3), rhs: Relative(4) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 15 }, Mov { destination: Relative(15), source: Direct(0) }, Mov { destination: Relative(16), source: Relative(9) }, Mov { destination: Relative(17), source: Relative(3) }, Mov { destination: Relative(18), source: Relative(6) }, Mov { destination: Relative(19), source: Relative(9) }, Mov { destination: Relative(20), source: Relative(3) }, Mov { destination: Relative(21), source: Relative(6) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(14) }, Call { location: 397 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(11), source: Relative(16) }, Mov { destination: Relative(12), source: Relative(17) }, Mov { destination: Relative(13), source: Relative(18) }, BinaryFieldOp { destination: Relative(14), op: Equals, lhs: Relative(11), rhs: Relative(4) }, JumpIf { condition: Relative(14), location: 316 }, Const { destination: Relative(15), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(15) } }, Mov { destination: Relative(11), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(11), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(9), input1_y: Relative(3), input1_infinite: Relative(6), input2_x: Relative(9), input2_y: Relative(10), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(14), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(32835) }, Load { destination: Relative(3), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(9), op: Equals, lhs: Relative(3), rhs: Relative(4) }, JumpIf { condition: Relative(9), location: 328 }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(11) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(9) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(2), input2_y: Relative(10), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(9), size: 3 } }), BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(32835) }, Load { destination: Relative(9), source_pointer: Relative(10) }, BinaryFieldOp { destination: Relative(3), op: Equals, lhs: Relative(9), rhs: Relative(4) }, JumpIf { condition: Relative(3), location: 340 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Const { destination: Relative(3), bit_size: Field, value: 4 }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(1), input2_y: Relative(3), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(10), size: 3 } }), BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(32835) }, Load { destination: Relative(3), source_pointer: Relative(10) }, BinaryFieldOp { destination: Relative(9), op: Equals, lhs: Relative(3), rhs: Relative(4) }, JumpIf { condition: Relative(9), location: 353 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(9) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(1), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(9), size: 3 } }), BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(32835) }, Load { destination: Relative(9), source_pointer: Relative(10) }, BinaryFieldOp { destination: Relative(3), op: Equals, lhs: Relative(9), rhs: Relative(4) }, JumpIf { condition: Relative(3), location: 365 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(9) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(4), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(4), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(9), size: 3 } }), BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(32835) }, Load { destination: Relative(9), source_pointer: Relative(10) }, BinaryFieldOp { destination: Relative(3), op: Equals, lhs: Relative(9), rhs: Relative(4) }, JumpIf { condition: Relative(3), location: 377 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(9) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(2), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(2), input2_y: Relative(1), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(9), size: 3 } }), BinaryIntOp { destination: Relative(2), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(32835) }, Load { destination: Relative(1), source_pointer: Relative(2) }, BinaryFieldOp { destination: Relative(2), op: Equals, lhs: Relative(1), rhs: Relative(4) }, JumpIf { condition: Relative(2), location: 389 }, Const { destination: Relative(3), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(3) } }, Jump { location: 390 }, Return, Const { destination: Direct(32772), bit_size: Integer(U32), value: 30720 }, BinaryIntOp { destination: Direct(32771), op: LessThan, bit_size: U32, lhs: Direct(0), rhs: Direct(32772) }, JumpIf { condition: Direct(32771), location: 396 }, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 17843811134343075018 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, Call { location: 391 }, JumpIf { condition: Relative(3), location: 426 }, Jump { location: 400 }, JumpIf { condition: Relative(6), location: 418 }, Jump { location: 402 }, Mov { destination: Relative(13), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(13), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(2), input1_infinite: Relative(3), input2_x: Relative(4), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(14), size: 3 } }), BinaryIntOp { destination: Relative(2), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(32835) }, Load { destination: Relative(1), source_pointer: Relative(2) }, BinaryIntOp { destination: Relative(3), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(32836) }, Load { destination: Relative(2), source_pointer: Relative(3) }, BinaryIntOp { destination: Relative(4), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(32837) }, Load { destination: Relative(3), source_pointer: Relative(4) }, Mov { destination: Relative(10), source: Relative(1) }, Mov { destination: Relative(11), source: Relative(2) }, Mov { destination: Relative(12), source: Relative(3) }, Jump { location: 422 }, Mov { destination: Relative(10), source: Relative(1) }, Mov { destination: Relative(11), source: Relative(2) }, Mov { destination: Relative(12), source: Relative(3) }, Jump { location: 422 }, Mov { destination: Relative(7), source: Relative(10) }, Mov { destination: Relative(8), source: Relative(11) }, Mov { destination: Relative(9), source: Relative(12) }, Jump { location: 430 }, Mov { destination: Relative(7), source: Relative(4) }, Mov { destination: Relative(8), source: Relative(5) }, Mov { destination: Relative(9), source: Relative(6) }, Jump { location: 430 }, Mov { destination: Relative(1), source: Relative(7) }, Mov { destination: Relative(2), source: Relative(8) }, Mov { destination: Relative(3), source: Relative(9) }, Return]" + "[Const { destination: Direct(2), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(1), bit_size: Integer(U32), value: 32841 }, Const { destination: Direct(0), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(4), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(5), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(32838), size_address: Relative(4), offset_address: Relative(5) }, Mov { destination: Relative(1), source: Direct(32838) }, Mov { destination: Relative(2), source: Direct(32839) }, Mov { destination: Relative(3), source: Direct(32840) }, Call { location: 14 }, Call { location: 18 }, Const { destination: Relative(1), bit_size: Integer(U32), value: 32841 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Stop { return_data: HeapVector { pointer: Relative(1), size: Relative(2) } }, Const { destination: Direct(32835), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(32836), bit_size: Integer(U32), value: 2 }, Const { destination: Direct(32837), bit_size: Integer(U32), value: 3 }, Return, Call { location: 252 }, Const { destination: Relative(4), bit_size: Field, value: 1 }, Const { destination: Relative(5), bit_size: Field, value: 17631683881184975370165255887551781615748388533673675138860 }, Const { destination: Relative(6), bit_size: Integer(U1), value: 0 }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Mov { destination: Relative(9), source: Relative(8) }, Store { destination_pointer: Relative(9), source: Relative(4) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(5) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(6) }, Const { destination: Relative(8), bit_size: Field, value: 0 }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Mov { destination: Relative(11), source: Relative(10) }, Store { destination_pointer: Relative(11), source: Relative(1) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Store { destination_pointer: Relative(11), source: Relative(8) }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(11), size: Relative(12) }, scalars: HeapVector { pointer: Relative(13), size: Relative(14) }, outputs: HeapArray { pointer: Relative(15), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(32835) }, Load { destination: Relative(11), source_pointer: Relative(12) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(32836) }, Load { destination: Relative(12), source_pointer: Relative(13) }, BinaryFieldOp { destination: Relative(13), op: Equals, lhs: Relative(11), rhs: Relative(2) }, JumpIf { condition: Relative(13), location: 61 }, Const { destination: Relative(14), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(14) } }, BinaryFieldOp { destination: Relative(11), op: Equals, lhs: Relative(12), rhs: Relative(3) }, JumpIf { condition: Relative(11), location: 65 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, Const { destination: Relative(14), bit_size: Integer(U32), value: 15 }, Mov { destination: Relative(15), source: Direct(0) }, Mov { destination: Relative(16), source: Relative(2) }, Mov { destination: Relative(17), source: Relative(3) }, Mov { destination: Relative(18), source: Relative(6) }, Mov { destination: Relative(19), source: Relative(2) }, Mov { destination: Relative(20), source: Relative(3) }, Mov { destination: Relative(21), source: Relative(6) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(14) }, Call { location: 258 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(11), source: Relative(16) }, Mov { destination: Relative(12), source: Relative(17) }, Mov { destination: Relative(13), source: Relative(18) }, Const { destination: Relative(17), bit_size: Integer(U32), value: 18 }, Mov { destination: Relative(18), source: Direct(0) }, Mov { destination: Relative(19), source: Relative(4) }, Mov { destination: Relative(20), source: Relative(5) }, Mov { destination: Relative(21), source: Relative(6) }, Mov { destination: Relative(22), source: Relative(4) }, Mov { destination: Relative(23), source: Relative(5) }, Mov { destination: Relative(24), source: Relative(6) }, BinaryIntOp { destination: Direct(0), op: Add, bit_size: U32, lhs: Direct(0), rhs: Relative(17) }, Call { location: 258 }, Mov { destination: Direct(0), source: Relative(0) }, Mov { destination: Relative(14), source: Relative(19) }, Mov { destination: Relative(15), source: Relative(20) }, Mov { destination: Relative(16), source: Relative(21) }, BinaryFieldOp { destination: Relative(17), op: Equals, lhs: Relative(14), rhs: Relative(11) }, JumpIf { condition: Relative(17), location: 97 }, Const { destination: Relative(18), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(18) } }, Mov { destination: Relative(11), source: Direct(1) }, Const { destination: Relative(17), bit_size: Integer(U32), value: 7 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(17) }, IndirectConst { destination_pointer: Relative(11), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Mov { destination: Relative(18), source: Relative(17) }, Store { destination_pointer: Relative(18), source: Relative(4) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(5) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(6) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(4) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(5) }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, Store { destination_pointer: Relative(18), source: Relative(6) }, Mov { destination: Relative(17), source: Direct(1) }, Const { destination: Relative(18), bit_size: Integer(U32), value: 5 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(18) }, IndirectConst { destination_pointer: Relative(17), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(17), rhs: Direct(2) }, Mov { destination: Relative(19), source: Relative(18) }, Store { destination_pointer: Relative(19), source: Relative(1) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(8) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(1) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(8) }, Mov { destination: Relative(18), source: Direct(1) }, Const { destination: Relative(19), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(19) }, IndirectConst { destination_pointer: Relative(18), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Const { destination: Relative(20), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(21), op: Add, bit_size: U32, lhs: Relative(17), rhs: Direct(2) }, Const { destination: Relative(22), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Relative(23), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(19), size: Relative(20) }, scalars: HeapVector { pointer: Relative(21), size: Relative(22) }, outputs: HeapArray { pointer: Relative(23), size: 3 } }), BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(18), rhs: Direct(32835) }, Load { destination: Relative(11), source_pointer: Relative(17) }, BinaryFieldOp { destination: Relative(17), op: Equals, lhs: Relative(14), rhs: Relative(11) }, JumpIf { condition: Relative(17), location: 143 }, Const { destination: Relative(18), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(18) } }, Const { destination: Relative(11), bit_size: Field, value: 23 }, Mov { destination: Relative(17), source: Direct(1) }, Const { destination: Relative(18), bit_size: Integer(U32), value: 9 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(18) }, IndirectConst { destination_pointer: Relative(17), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(17), rhs: Direct(2) }, Mov { destination: Relative(19), source: Relative(18) }, Store { destination_pointer: Relative(19), source: Relative(1) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(8) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(11) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(8) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(1) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(8) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(4) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(8) }, Const { destination: Relative(1), bit_size: Field, value: 10456889356757736161582760391335869408742580538510966583040563008531594628700 }, Const { destination: Relative(8), bit_size: Field, value: 4714263418031017792755226781102360879566029698463912436805212494059649164343 }, Mov { destination: Relative(11), source: Direct(1) }, Const { destination: Relative(18), bit_size: Integer(U32), value: 13 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(18) }, IndirectConst { destination_pointer: Relative(11), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Mov { destination: Relative(19), source: Relative(18) }, Store { destination_pointer: Relative(19), source: Relative(4) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(5) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(6) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(14) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(15) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(16) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(2) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(3) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(6) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(1) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(8) }, BinaryIntOp { destination: Relative(19), op: Add, bit_size: U32, lhs: Relative(19), rhs: Direct(2) }, Store { destination_pointer: Relative(19), source: Relative(6) }, Mov { destination: Relative(1), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(1), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 12 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(17), rhs: Direct(2) }, Const { destination: Relative(16), bit_size: Integer(U32), value: 8 }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(8), size: Relative(14) }, scalars: HeapVector { pointer: Relative(15), size: Relative(16) }, outputs: HeapArray { pointer: Relative(18), size: 3 } }), BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(32835) }, Load { destination: Relative(8), source_pointer: Relative(11) }, Const { destination: Relative(1), bit_size: Field, value: -7349266043899242844836273743257843180744506495159104166319746739537754653274 }, BinaryFieldOp { destination: Relative(11), op: Equals, lhs: Relative(8), rhs: Relative(1) }, JumpIf { condition: Relative(11), location: 213 }, Const { destination: Relative(14), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(14) } }, Load { destination: Relative(1), source_pointer: Relative(9) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(11), op: Equals, bit_size: U32, lhs: Relative(8), rhs: Relative(1) }, Not { destination: Relative(11), source: Relative(11), bit_size: U1 }, JumpIf { condition: Relative(11), location: 219 }, Call { location: 295 }, BinaryIntOp { destination: Relative(1), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(1) }, Load { destination: Relative(1), source_pointer: Relative(7) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(11), op: Equals, bit_size: U32, lhs: Relative(9), rhs: Relative(1) }, Not { destination: Relative(11), source: Relative(11), bit_size: U1 }, JumpIf { condition: Relative(11), location: 227 }, Call { location: 295 }, BinaryIntOp { destination: Relative(1), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Store { destination_pointer: Relative(7), source: Relative(1) }, Load { destination: Relative(1), source_pointer: Relative(10) }, Const { destination: Relative(7), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(11), op: Equals, bit_size: U32, lhs: Relative(7), rhs: Relative(1) }, Not { destination: Relative(11), source: Relative(11), bit_size: U1 }, JumpIf { condition: Relative(11), location: 235 }, Call { location: 295 }, BinaryIntOp { destination: Relative(1), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Store { destination_pointer: Relative(10), source: Relative(1) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(32837) }, Load { destination: Relative(1), source_pointer: Relative(11) }, BinaryIntOp { destination: Relative(10), op: Equals, bit_size: U1, lhs: Relative(1), rhs: Relative(6) }, JumpIf { condition: Relative(10), location: 243 }, Const { destination: Relative(11), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(11) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(2), rhs: Relative(4) }, JumpIf { condition: Relative(1), location: 247 }, Const { destination: Relative(6), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(6) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(3), rhs: Relative(5) }, JumpIf { condition: Relative(1), location: 251 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(2) } }, Return, Const { destination: Direct(32772), bit_size: Integer(U32), value: 30720 }, BinaryIntOp { destination: Direct(32771), op: LessThan, bit_size: U32, lhs: Direct(0), rhs: Direct(32772) }, JumpIf { condition: Direct(32771), location: 257 }, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 17843811134343075018 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, Call { location: 252 }, JumpIf { condition: Relative(3), location: 287 }, Jump { location: 261 }, JumpIf { condition: Relative(6), location: 279 }, Jump { location: 263 }, Mov { destination: Relative(13), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(13), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(2), input1_infinite: Relative(3), input2_x: Relative(4), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(14), size: 3 } }), BinaryIntOp { destination: Relative(2), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(32835) }, Load { destination: Relative(1), source_pointer: Relative(2) }, BinaryIntOp { destination: Relative(3), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(32836) }, Load { destination: Relative(2), source_pointer: Relative(3) }, BinaryIntOp { destination: Relative(4), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(32837) }, Load { destination: Relative(3), source_pointer: Relative(4) }, Mov { destination: Relative(10), source: Relative(1) }, Mov { destination: Relative(11), source: Relative(2) }, Mov { destination: Relative(12), source: Relative(3) }, Jump { location: 283 }, Mov { destination: Relative(10), source: Relative(1) }, Mov { destination: Relative(11), source: Relative(2) }, Mov { destination: Relative(12), source: Relative(3) }, Jump { location: 283 }, Mov { destination: Relative(7), source: Relative(10) }, Mov { destination: Relative(8), source: Relative(11) }, Mov { destination: Relative(9), source: Relative(12) }, Jump { location: 291 }, Mov { destination: Relative(7), source: Relative(4) }, Mov { destination: Relative(8), source: Relative(5) }, Mov { destination: Relative(9), source: Relative(6) }, Jump { location: 291 }, Mov { destination: Relative(1), source: Relative(7) }, Mov { destination: Relative(2), source: Relative(8) }, Mov { destination: Relative(3), source: Relative(9) }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 12049594436772143978 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return]" ], - "debug_symbols": "tZndTls7EEbfJddcbHv821epqiqFUEWKAkrhSEeIdz8ze7wSzsVGZUNu+BalXmw7HsdDXjZ3u1/Pv3/uj/cPfzbfvr9sfp32h8P+98/Dw+32af9w1H992Uz2JfTNt3CziZNH8Ige4pE8skfxqB7Nwy3iFnGLuEXcIm4Rt4hbxC3iFnFLcktyS3JLUotoJI/sUTyqR/Poc+TJI3hED7UkjeSRPYqHWrJG8+hzlMlDLUUjeohH8lBL0yge1aN59Dnq5BE8ood4JA+3VLdUt1S3VFuX6WbTppFhZBwpI9PIPLKMrCPbyOHrw9eHrw9fN5+ueU8j88gyso5sI7tnmCYgABEQIAEZKEAFGoA5YA6YA+aAOWAOmAPmgDlgDpgj5og5Yo6YI+aIOWKe60AMGtAHzNUwQwAiIEACMlAAMyeDBphZd2OYK2SGAETAzNUgARkoQAUa0AdY1TgEIAKYM+aMOWPOmDPmjLlgLpgL5oK5YC6YC+aCuWAumCvmirlirpgr5oq5Yq6YK+aKuWFumBvmhrlhbpgb5oa5YW6YO+aOuWPumDvmjrlj7pg75j7McZqAAERAgARkwMzNoAJm7gZ9wFyDMwQgAmqO8/tHAjJQgAo0oA+wGnQIQAQwR8wRc8QcMUfMEbNgFsyCWTALZsEsmAWzYBbMCXPCnDBbDcZokIAMFKACDTCz2PvsBAQgAgIkIAMFqEADMBfMVoMxGZinGGSgABVoQB9gFecQgAgIgLlirpgr5orZKi7aPrSKcwhABMxsm80qziEDBahAA/oAqziZDAJgd4L58iJAAjJgNwx7dazixJbOKk6yQXcQqziHAERAgARkoAAVaADmgDlgtoqTYiBAAjJg5mZQgQb0AVZxDgEwczcQwG5Jk0EGClABNado0AdYxTkEIAICmFkMMmDmZFCBBvQBVnHJJmgV5xABARKQgQKYuRo0wMw2d6s4hwBEQM3ZZmoV55CBAlSgAXZ7nK+5E6DmbHO3dz0HARJgZpup1aBDBRrQB1gNOpjZ9obVoIOZbcpWgw4ZKICZbYJWgw59gNWgQwAiYGbbG1aDDmouNmWrQYcKNIdk5VCigQAJyEABKmDD7T5v5TCDlYNDACJgZnl9vdnQ4vx8Ou121uG86Xm0E3rcnnbHp8234/PhcLP5Z3t4nv/Tn8ftcc6n7Ul/qk+9O95pqvB+f9gZvd5cRk/LQ/VUGoP1WDoPz389Xl/PMT7FtjQ+Lo9PuScEJV0mEMo6gywZ3plDSuc55LxiDVLpjG+yYnzpvAY1hKXx9Z3xkecvOayYf7W3DP/9svga9uXxesGvQ6AX+rbmCazI/QnqmhVshRXoMi2ND5/fhuGq+1CbTWEdpzKtWAftws6GLIsrGcrnV6JcdSVyYkNo39XXrESrPIM2G2nxZJo+fzRN11wJbZCoLe2M0oqV0LaH9wdtfFYZJDML7TUWd1XM1zuitKOJ50fodc0kkvWJbkh58ZiN7Z09pSt5Puj0jytpcUt8QFLXrEYql7nUtmY1cjlvilzWFJh2TGdDTasMLZy3douLlw9JV9xWLb25/kyrJtF4BG3VFqtL6hdsq49IVm2rLpe5pLDmNhgj7z/ahi2+pHbf+vRqfESyZjW0a7zMZdW9Tjs2LobamMXF1chfsRr5yquR02UueU25aw9HrWnPtnhopf4Vq9GvvBotXuYiq3qGKXN8auu4uLuyfMFqfESyZjW00z3PRT/6WLMaItRa0j8nLK7GV5yi+cqnqHZAl7n0Vf3gdK61MvXFi2f5ilO0rD5Ff+h329v96X+f0r6a7bTf/jrsxrf3z8fbNz99+veRn/Ap7+Pp4XZ393zamenNR7369bv0cCO9/Hi13/cf", + "debug_symbols": "tZfBThsxFAD/Zc852M/2s82vVAgFCFWkKKA0qVSh/HvtfR5KD4uqpVwyE4InWSfe9b5Oj7v7y/e7/fHp+cd08+11uj/tD4f997vD88P2vH8+tr++Tq4/+Drd+M0kzuANYgiGaEgGNWRDMVglWCVYJVglWCVYJVglWCVYJVglWCVaJVolWiW2SmiIhmRQQzYUQ52RnMEbxNAqsSEakkENrZIaiqHOUGdoFW0QQzBEQ6uUBjVkQzHUGdkZvEEMwRANVslWyVbJVsl9XtxmKm7QD8pgGIyDaVAH82AZHL06enX06ujV3mtzXuNgGtTBPFgGq9E7h3hEkIBEJCGKZKQglD1lT9lT9pQ9ZU/ZU/aUPWVPWSgLZaEslIWyUBbK8zoIXQpSh8yrYRaPCBKQiCREkV6OXQrSy+3X6OcVMotHBOnl3CUiCVEkIwWpQ/qqMfGIIJQT5UQ5UU6UE+VEWSkrZaWslJWyUlbKSlkpK+VMOVPOlDPlTDlTzpQz5Uw5Uy6UC+VCuVAulAvlQrlQLpQL5Uq5Uq6UK+VKuVKulCvlSrmOsjiHeESQgEQkIb1cumSkl2uXOmReg7N4RJBWlvn6EZGEKJKRgtQhfQ2aeEQQykJZKAtloSyUhXKgHCgHyoFyoBwoB8p9DYp0KUgvh35RdIhHBAlIRBKiSEYKQjlR7utCUpeIJESRjBSkd7RfoR3iEUEC0st6vW4mtgZ359Nu13cG7/YKbQfxsj3tjufp5ng5HDbTz+3hMv/Tj5ftceZ5e2qvtovH7vjY2IJP+8Ou23XzZ7RbHioljcFS9G14+ufxIfsxPkpZGi/L42OqkYDGPwfgdV0hLBU+OIYY344hpRVzELUyvoQV47XyHWTvl8bnD8YLn1+TX3H8OQjvHxa/w7o8vl0Y8wi0C2FZ8wmS8gnymhksygzU4JbG+8//DP2X/g7bJi0wj07dinlou5e3QgqLM+n18zOhXzoTKfKDaPuVumYmSuYztIt0XDwzuc+fmtxXzkTbWLC22o4irjm7uMjpSV1dPoz4wWS27frbCm+78fg/IvmvyG17tn3Yn/66V7722mm/vT/sxtOny/Hh3avnXy+8wr32y+n5Yfd4Oe166d0Nd3v8Jkk27Y1v+41If9rOu1Lz7bW//W8=", "file_map": { "16": { "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the\n// underlying proof system.\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n let mut result = embedded_curve_add_unsafe(point1_1, point2_1);\n\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n let double = embedded_curve_add_unsafe(point1, point1);\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n result = if double_predicate { double } else { result };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n // Ensure is_infinite is comptime\n let point1_1 = EmbeddedCurvePoint { x: point1.x, y: point1.y, is_infinite: false };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n embedded_curve_add_unsafe(point1_1, point2_1)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2)[0]\n}\n", diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_0.snap b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_0.snap index 3ebd817e856..706aeb57026 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_0.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_0.snap @@ -31,6 +31,10 @@ expression: artifact ], "return_type": null, "error_types": { + "12049594436772143978": { + "error_kind": "string", + "string": "array ref-count underflow detected" + }, "17843811134343075018": { "error_kind": "string", "string": "Stack too deep" @@ -45,9 +49,9 @@ expression: artifact "return value indices : []", "BRILLIG CALL func 0: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(1))], q_c: 0 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })], outputs: []", "unconstrained func 0", - "[Const { destination: Direct(2), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(1), bit_size: Integer(U32), value: 32839 }, Const { destination: Direct(0), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(4), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(5), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(32836), size_address: Relative(4), offset_address: Relative(5) }, Mov { destination: Relative(1), source: Direct(32836) }, Mov { destination: Relative(2), source: Direct(32837) }, Mov { destination: Relative(3), source: Direct(32838) }, Call { location: 14 }, Call { location: 15 }, Const { destination: Relative(1), bit_size: Integer(U32), value: 32839 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Stop { return_data: HeapVector { pointer: Relative(1), size: Relative(2) } }, Return, Call { location: 349 }, Const { destination: Relative(4), bit_size: Field, value: 1 }, Const { destination: Relative(5), bit_size: Field, value: 17631683881184975370165255887551781615748388533673675138860 }, Const { destination: Relative(6), bit_size: Integer(U1), value: 0 }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Mov { destination: Relative(9), source: Relative(8) }, Store { destination_pointer: Relative(9), source: Relative(4) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(5) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(6) }, Const { destination: Relative(8), bit_size: Field, value: 0 }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Mov { destination: Relative(11), source: Relative(10) }, Store { destination_pointer: Relative(11), source: Relative(1) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Store { destination_pointer: Relative(11), source: Relative(8) }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(11), size: Relative(12) }, scalars: HeapVector { pointer: Relative(13), size: Relative(14) }, outputs: HeapArray { pointer: Relative(15), size: 3 } }), Const { destination: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(7) }, Load { destination: Relative(9), source_pointer: Relative(11) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(11) }, Load { destination: Relative(12), source_pointer: Relative(13) }, BinaryFieldOp { destination: Relative(10), op: Equals, lhs: Relative(9), rhs: Relative(2) }, JumpIf { condition: Relative(10), location: 60 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, BinaryFieldOp { destination: Relative(9), op: Equals, lhs: Relative(12), rhs: Relative(3) }, JumpIf { condition: Relative(9), location: 64 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(2), input1_y: Relative(3), input1_infinite: Relative(6), input2_x: Relative(2), input2_y: Relative(3), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(10), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(9), rhs: Relative(7) }, Load { destination: Relative(10), source_pointer: Relative(12) }, Const { destination: Relative(9), bit_size: Field, value: 3078034153852398078128400807926804309327113743808504829582559963737223069694 }, BinaryFieldOp { destination: Relative(12), op: Equals, lhs: Relative(9), rhs: Relative(10) }, JumpIf { condition: Relative(12), location: 77 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 7 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(12) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, Mov { destination: Relative(13), source: Relative(12) }, Store { destination_pointer: Relative(13), source: Relative(4) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(5) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(6) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(4) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(5) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(6) }, Mov { destination: Relative(12), source: Direct(1) }, Const { destination: Relative(13), bit_size: Integer(U32), value: 5 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(13) }, IndirectConst { destination_pointer: Relative(12), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Mov { destination: Relative(14), source: Relative(13) }, Store { destination_pointer: Relative(14), source: Relative(1) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(8) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(1) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(8) }, Mov { destination: Relative(13), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(13), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, Const { destination: Relative(15), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Const { destination: Relative(17), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(14), size: Relative(15) }, scalars: HeapVector { pointer: Relative(16), size: Relative(17) }, outputs: HeapArray { pointer: Relative(18), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(13), rhs: Relative(7) }, Load { destination: Relative(10), source_pointer: Relative(12) }, BinaryFieldOp { destination: Relative(12), op: Equals, lhs: Relative(9), rhs: Relative(10) }, JumpIf { condition: Relative(12), location: 123 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 7 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Mov { destination: Relative(12), source: Relative(10) }, Store { destination_pointer: Relative(12), source: Relative(1) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(8) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(1) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(8) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(4) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(8) }, Const { destination: Relative(10), bit_size: Field, value: 11179562631109628533987091031692370366552561688588090155835439555627259799605 }, Const { destination: Relative(12), bit_size: Field, value: 3443719903172018228650470536370404288991794296383447657609081676265727805364 }, Mov { destination: Relative(13), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 10 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(13), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Mov { destination: Relative(15), source: Relative(14) }, Store { destination_pointer: Relative(15), source: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(5) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(2) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(3) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(10) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(12) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(12) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 9 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Const { destination: Relative(16), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(12), size: Relative(14) }, scalars: HeapVector { pointer: Relative(15), size: Relative(16) }, outputs: HeapArray { pointer: Relative(17), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(7) }, Load { destination: Relative(9), source_pointer: Relative(12) }, Const { destination: Relative(10), bit_size: Field, value: -7349266043899242844836273743257843180744506495159104166319746739537754653274 }, BinaryFieldOp { destination: Relative(12), op: Equals, lhs: Relative(9), rhs: Relative(10) }, JumpIf { condition: Relative(12), location: 182 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Mov { destination: Relative(12), source: Relative(10) }, Store { destination_pointer: Relative(12), source: Relative(1) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(8) }, Mov { destination: Relative(1), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(1), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Mov { destination: Relative(10), source: Relative(8) }, Store { destination_pointer: Relative(10), source: Relative(4) }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, Store { destination_pointer: Relative(10), source: Relative(5) }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, Store { destination_pointer: Relative(10), source: Relative(6) }, Mov { destination: Relative(8), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(8), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(10), size: Relative(12) }, scalars: HeapVector { pointer: Relative(13), size: Relative(14) }, outputs: HeapArray { pointer: Relative(15), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(7) }, Load { destination: Relative(1), source_pointer: Relative(9) }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(11) }, Load { destination: Relative(9), source_pointer: Relative(10) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(10) }, Load { destination: Relative(11), source_pointer: Relative(12) }, BinaryIntOp { destination: Relative(8), op: Equals, bit_size: U1, lhs: Relative(11), rhs: Relative(6) }, JumpIf { condition: Relative(8), location: 223 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(1), rhs: Relative(4) }, JumpIf { condition: Relative(8), location: 227 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(9), rhs: Relative(5) }, JumpIf { condition: Relative(1), location: 231 }, Const { destination: Relative(8), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(8) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(2), rhs: Relative(3) }, JumpIf { condition: Relative(1), location: 234 }, Jump { location: 348 }, Const { destination: Relative(1), bit_size: Field, value: 2 }, Mov { destination: Relative(5), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(5), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(4), input1_y: Relative(1), input1_infinite: Relative(6), input2_x: Relative(4), input2_y: Relative(1), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(8), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(5), rhs: Relative(7) }, Load { destination: Relative(8), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(5), op: Equals, lhs: Relative(8), rhs: Relative(4) }, JumpIf { condition: Relative(5), location: 247 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Const { destination: Relative(5), bit_size: Field, value: 3 }, Mov { destination: Relative(8), source: Direct(1) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(9) }, IndirectConst { destination_pointer: Relative(8), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(4), input1_y: Relative(1), input1_infinite: Relative(6), input2_x: Relative(4), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(9), size: 3 } }), BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(7) }, Load { destination: Relative(9), source_pointer: Relative(10) }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(9), rhs: Relative(4) }, JumpIf { condition: Relative(8), location: 260 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, BinaryFieldOp { destination: Relative(8), op: Add, lhs: Relative(2), rhs: Relative(4) }, BinaryFieldOp { destination: Relative(9), op: Add, lhs: Relative(3), rhs: Relative(4) }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(8), input1_y: Relative(3), input1_infinite: Relative(6), input2_x: Relative(8), input2_y: Relative(3), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(11), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(7) }, Load { destination: Relative(11), source_pointer: Relative(12) }, BinaryFieldOp { destination: Relative(10), op: Equals, lhs: Relative(11), rhs: Relative(4) }, JumpIf { condition: Relative(10), location: 274 }, Const { destination: Relative(12), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(12) } }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(8), input1_y: Relative(3), input1_infinite: Relative(6), input2_x: Relative(8), input2_y: Relative(9), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(11), size: 3 } }), BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(7) }, Load { destination: Relative(3), source_pointer: Relative(8) }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(3), rhs: Relative(4) }, JumpIf { condition: Relative(8), location: 286 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(2), input2_y: Relative(9), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(8), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(3), rhs: Relative(7) }, Load { destination: Relative(8), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(3), op: Equals, lhs: Relative(8), rhs: Relative(4) }, JumpIf { condition: Relative(3), location: 298 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Const { destination: Relative(3), bit_size: Field, value: 4 }, Mov { destination: Relative(8), source: Direct(1) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(9) }, IndirectConst { destination_pointer: Relative(8), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(1), input2_y: Relative(3), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(9), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(7) }, Load { destination: Relative(3), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(3), rhs: Relative(4) }, JumpIf { condition: Relative(8), location: 311 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(1), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(8), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(3), rhs: Relative(7) }, Load { destination: Relative(8), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(3), op: Equals, lhs: Relative(8), rhs: Relative(4) }, JumpIf { condition: Relative(3), location: 323 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(4), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(4), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(8), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(3), rhs: Relative(7) }, Load { destination: Relative(8), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(3), op: Equals, lhs: Relative(8), rhs: Relative(4) }, JumpIf { condition: Relative(3), location: 335 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(2), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(2), input2_y: Relative(1), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(8), size: 3 } }), BinaryIntOp { destination: Relative(2), op: Add, bit_size: U32, lhs: Relative(3), rhs: Relative(7) }, Load { destination: Relative(1), source_pointer: Relative(2) }, BinaryFieldOp { destination: Relative(2), op: Equals, lhs: Relative(1), rhs: Relative(4) }, JumpIf { condition: Relative(2), location: 347 }, Const { destination: Relative(3), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(3) } }, Jump { location: 348 }, Return, Const { destination: Direct(32772), bit_size: Integer(U32), value: 30720 }, BinaryIntOp { destination: Direct(32771), op: LessThan, bit_size: U32, lhs: Direct(0), rhs: Direct(32772) }, JumpIf { condition: Direct(32771), location: 354 }, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 17843811134343075018 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return]" + "[Const { destination: Direct(2), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(1), bit_size: Integer(U32), value: 32839 }, Const { destination: Direct(0), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(4), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(5), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(32836), size_address: Relative(4), offset_address: Relative(5) }, Mov { destination: Relative(1), source: Direct(32836) }, Mov { destination: Relative(2), source: Direct(32837) }, Mov { destination: Relative(3), source: Direct(32838) }, Call { location: 14 }, Call { location: 15 }, Const { destination: Relative(1), bit_size: Integer(U32), value: 32839 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Stop { return_data: HeapVector { pointer: Relative(1), size: Relative(2) } }, Return, Call { location: 222 }, Const { destination: Relative(4), bit_size: Field, value: 1 }, Const { destination: Relative(5), bit_size: Field, value: 17631683881184975370165255887551781615748388533673675138860 }, Const { destination: Relative(6), bit_size: Integer(U1), value: 0 }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Mov { destination: Relative(9), source: Relative(8) }, Store { destination_pointer: Relative(9), source: Relative(4) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(5) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(6) }, Const { destination: Relative(8), bit_size: Field, value: 0 }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Mov { destination: Relative(11), source: Relative(10) }, Store { destination_pointer: Relative(11), source: Relative(1) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Store { destination_pointer: Relative(11), source: Relative(8) }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(11), size: Relative(12) }, scalars: HeapVector { pointer: Relative(13), size: Relative(14) }, outputs: HeapArray { pointer: Relative(15), size: 3 } }), Const { destination: Relative(11), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(11) }, Load { destination: Relative(12), source_pointer: Relative(13) }, Const { destination: Relative(13), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(13) }, Load { destination: Relative(14), source_pointer: Relative(15) }, BinaryFieldOp { destination: Relative(13), op: Equals, lhs: Relative(12), rhs: Relative(2) }, JumpIf { condition: Relative(13), location: 60 }, Const { destination: Relative(15), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(15) } }, BinaryFieldOp { destination: Relative(12), op: Equals, lhs: Relative(14), rhs: Relative(3) }, JumpIf { condition: Relative(12), location: 64 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, Mov { destination: Relative(12), source: Direct(1) }, Const { destination: Relative(13), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(13) }, IndirectConst { destination_pointer: Relative(12), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(2), input1_y: Relative(3), input1_infinite: Relative(6), input2_x: Relative(2), input2_y: Relative(3), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(13), size: 3 } }), BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(12), rhs: Relative(11) }, Load { destination: Relative(13), source_pointer: Relative(14) }, Const { destination: Relative(12), bit_size: Field, value: 3078034153852398078128400807926804309327113743808504829582559963737223069694 }, BinaryFieldOp { destination: Relative(14), op: Equals, lhs: Relative(12), rhs: Relative(13) }, JumpIf { condition: Relative(14), location: 77 }, Const { destination: Relative(15), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(15) } }, Mov { destination: Relative(13), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 7 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(13), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Mov { destination: Relative(15), source: Relative(14) }, Store { destination_pointer: Relative(15), source: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(5) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(5) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, Mov { destination: Relative(14), source: Direct(1) }, Const { destination: Relative(15), bit_size: Integer(U32), value: 5 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(15) }, IndirectConst { destination_pointer: Relative(14), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Mov { destination: Relative(16), source: Relative(15) }, Store { destination_pointer: Relative(16), source: Relative(1) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(8) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(1) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(8) }, Mov { destination: Relative(15), source: Direct(1) }, Const { destination: Relative(16), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(16) }, IndirectConst { destination_pointer: Relative(15), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Const { destination: Relative(17), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Const { destination: Relative(19), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Relative(20), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(16), size: Relative(17) }, scalars: HeapVector { pointer: Relative(18), size: Relative(19) }, outputs: HeapArray { pointer: Relative(20), size: 3 } }), BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(15), rhs: Relative(11) }, Load { destination: Relative(13), source_pointer: Relative(14) }, BinaryFieldOp { destination: Relative(14), op: Equals, lhs: Relative(12), rhs: Relative(13) }, JumpIf { condition: Relative(14), location: 123 }, Const { destination: Relative(15), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(15) } }, Mov { destination: Relative(12), source: Direct(1) }, Const { destination: Relative(13), bit_size: Integer(U32), value: 7 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(13) }, IndirectConst { destination_pointer: Relative(12), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Mov { destination: Relative(14), source: Relative(13) }, Store { destination_pointer: Relative(14), source: Relative(1) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(8) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(1) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(8) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(4) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(8) }, Const { destination: Relative(1), bit_size: Field, value: 11179562631109628533987091031692370366552561688588090155835439555627259799605 }, Const { destination: Relative(8), bit_size: Field, value: 3443719903172018228650470536370404288991794296383447657609081676265727805364 }, Mov { destination: Relative(13), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 10 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(13), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Mov { destination: Relative(15), source: Relative(14) }, Store { destination_pointer: Relative(15), source: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(5) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(2) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(3) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(1) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(8) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, Mov { destination: Relative(1), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(1), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 9 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Const { destination: Relative(16), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(8), size: Relative(14) }, scalars: HeapVector { pointer: Relative(15), size: Relative(16) }, outputs: HeapArray { pointer: Relative(17), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(1), rhs: Relative(11) }, Load { destination: Relative(8), source_pointer: Relative(12) }, Const { destination: Relative(1), bit_size: Field, value: -7349266043899242844836273743257843180744506495159104166319746739537754653274 }, BinaryFieldOp { destination: Relative(11), op: Equals, lhs: Relative(8), rhs: Relative(1) }, JumpIf { condition: Relative(11), location: 182 }, Const { destination: Relative(12), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(12) } }, Load { destination: Relative(1), source_pointer: Relative(9) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(11), op: Equals, bit_size: U32, lhs: Relative(8), rhs: Relative(1) }, Not { destination: Relative(11), source: Relative(11), bit_size: U1 }, JumpIf { condition: Relative(11), location: 188 }, Call { location: 228 }, BinaryIntOp { destination: Relative(1), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(1) }, Load { destination: Relative(1), source_pointer: Relative(7) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(11), op: Equals, bit_size: U32, lhs: Relative(9), rhs: Relative(1) }, Not { destination: Relative(11), source: Relative(11), bit_size: U1 }, JumpIf { condition: Relative(11), location: 196 }, Call { location: 228 }, BinaryIntOp { destination: Relative(1), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Store { destination_pointer: Relative(7), source: Relative(1) }, Load { destination: Relative(1), source_pointer: Relative(10) }, Const { destination: Relative(7), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(11), op: Equals, bit_size: U32, lhs: Relative(7), rhs: Relative(1) }, Not { destination: Relative(11), source: Relative(11), bit_size: U1 }, JumpIf { condition: Relative(11), location: 204 }, Call { location: 228 }, BinaryIntOp { destination: Relative(1), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Store { destination_pointer: Relative(10), source: Relative(1) }, Const { destination: Relative(1), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(1) }, Load { destination: Relative(11), source_pointer: Relative(12) }, BinaryIntOp { destination: Relative(1), op: Equals, bit_size: U1, lhs: Relative(11), rhs: Relative(6) }, JumpIf { condition: Relative(1), location: 213 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(2), rhs: Relative(4) }, JumpIf { condition: Relative(1), location: 217 }, Const { destination: Relative(6), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(6) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(3), rhs: Relative(5) }, JumpIf { condition: Relative(1), location: 221 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(2) } }, Return, Const { destination: Direct(32772), bit_size: Integer(U32), value: 30720 }, BinaryIntOp { destination: Direct(32771), op: LessThan, bit_size: U32, lhs: Direct(0), rhs: Direct(32772) }, JumpIf { condition: Direct(32771), location: 227 }, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 17843811134343075018 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 12049594436772143978 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return]" ], - "debug_symbols": "tZndThs9EIbvJccc2J4f29xKVaEAoYoUBZTCJ31C3Htndvwm9GBR2SQnfR9K/TT2euxZ5X31uLl/+3W33T89/17d/nhf3R+2u932193u+WH9un3e29++r5L/kXV1m29WuUa0iD5FSRE5okRQBEdIRFhKWEpYSlgoLBQWCguFhcJCYaGwUFgoLBQWNgtZ5IgSQREcIREaUSNaRJ9CzMIWOaJEUARHSIRZxKJGtIg+hZpFLXJEiaAIn1GylJE6so5sI3tk9dWx+dU80tenWNJIHikjdWQd2Ub2yJZG5pHD14avDV8bvjZ8bfja8LXh68PXh68PXx++Pnx9+Prw9eHrw9eHL6cEyIACIAADBKAA97JDA/QBOQEyoAAIwAABKMDN4tAAbrZnmqdCmCADCsDNzYEBAlBABTRAHzAVxwQZUAAwE8wEM8FMMBPMBDPDzDAzzAwzw8wwM8wMM8PMMAvMArPALDALzAKzwCwwC8wCs8KsMCvMCrPCrDArzAqzwqwwV5grzBXmCnOFeaq17qAAM5fk0AB9gBdcQAaYufhe9ZoLYIAAFFABDdAHeOkFZADMHeYOc4e5w9xh7jD3YS4pATKgAAjAAAEooAIaAOYMc4bZa7CQAwEYIAAFVEADuJn99kmADCgAAjBAAAqogAaAmWD2Gizi4J7uIAAFVEAD9AFecQF+SSWHAvCLaro1GSAABfiF5VOerqwJ+gCvuIAMKAACuNln4RUX4GafjldcQAP0AV5xpA5urg5+KU5XOgEYIAAFVICZ2R+3V9wEXnHsH8wrLqAACOBm/xhecQEKqIAG6AO84tg/s1dcgJv9w3vFBTBAAG72p+MVF9AAfYBXXEAGmFn8CXrFBZhZpu5GAAqoAG8XfIJecQ7kFReQAQVAAAa4mR0U4GZxaIA+wCsuwM3VoQAIwAABKMDNzaEB3Ny9U0uADCgAb3ambo4BAlBABTSAmbV485cA3kL5lP3WCyAAA9zsE/QaDKiABugDvAYD3KwOBeBmn7LXYIAA3Fw/Pm5WaJDvXg+bjffHnzpm66Nf1ofN/nV1u3/b7W5W/613b9M/+v2y3k/5uj7Yb22bbPaPliZ82u42Th83p9Fpfqjt1zHYNuxxuPzzeKp5jOfS5saX+fEsnSFQPk0g6zIDzRm+mAPzcQ4iC9aAtWN8owXjteMZ1Jznxtcvxhd8fpU8N//2xfjEmICmPvsM+rzBGt9Uh8JY+AKOuuBJVlGsZF3yJJpiJTulufGZzt7O/65Ysp/tdYawkEnTgnWwPv9oEJpdyVzPX4l61ZUQxoawzr4vWYlW8RmsneXZEy6ff8Tla66EteAoLuu9ecFKWGONe8Za60UGEszC+tvZXVX0zKOu1LPPutIucNh9R7LktLNXgnJcz16XPBH2988wsMzePVQusBrfkSxaDdbTXGpbshqixx0uuuS0sBeMo6HyIkPLxzptZbYjo3ZmjVA/u0Y4XWBXfEeyaFc0/tTgpkVPpGE97TVt9txjvsRq8JVXo9NpLpyX9PuloDOwV7DZ/cmXOD/5yuenvTGe5rKocyfuqBQSKnMGucT5KVc+P+1yPs1FlpxdVCtqjVqaPYFFL7EaeuXVaOU0F1r0VpgEdwGn+d2llzhF9cqnKNu3KJiLfe2xZDWIUGtMOntu6CVOUb3yKcq2I45z6X8/2Z/20/phe/jrm88Pdx226/vdZvz49LZ/+PTb1/9f8Bt8c/pyeH7YPL4dNm769PWp/fnDjp0bK9efH/7//QE=", + "debug_symbols": "tZffTioxEIffZa+5aDszbcdXMcYgroaEAEE4yYnh3U+7Mz//XKwx6/HG70PsJ+1uKbwOj+PD5fl+u386vAw3t6/Dw2m7222f73eHzfq8Pezbb1+H0H/EPNzE1RCLoRp0QgqGaEgGMrBBDFZJVklWSVYhq5BVyCpkFbIKWYWsQlYhq5BVuFWoIRqSgQxsEEM2FEM16ARpFW6IhmQgAxvE0CrSUAzVoBNyq+SGaEgGMvQZhUZxZmdxVqcaS1+dNr8SnX19UiM52SnO7CzO6lRjDc7o9F71XvVe9V71XvVe9V71nnpPvafeU++p99R76j31nnpPvRdDgERIghCEIQLJkN7lLhWiLjFAIiRBCMIQgWRIL0uXCunldk3jtBEmiZAE6eXahSECyZACqRB1mTbHJBGSICgTyoQyoUwoE8qEMqPMKDPKjDKjzCgzyowyo8woC8qCsqAsKAvKgrKgLCgLyoJyRjmjnFHOKGeUM8oZ5YxyRjmjXFAuKBeUC8oF5WmvaZcMaeUUulSIuvQNZxIhrZz6vdr3nAlDBJIhBVIh6tK3nkmEoKwoK8qKsqKsKCvK6uUUAiRCEoQgDBFIL1OXAqmQXuZ+VARIhCQIQRgikAwpkApBOU3l63U14BC7P5/GsZ9hH061dtYd16dxfx5u9pfdbjX8We8u0x+9HNf7ief1qT3bLtS4f2xswaftbux2Xb2PDvNDUxUfnGp+Gy7fHk8l+nhOdW58mh/PooxA5vcJxLysQHOFL+bA/DYHkQVrwFkxvtKC8VlxDUqMc+PLF+MTXn+WODf/+sX4wJhADjp7DXS+0A6nUDzRXPg/NMqCK1kkYyXLkitRM1ZSKcyNj/Tj2/n7iSX3c/vIQVjIkMOCdWhn8VtBaHYlY/n5SpRfXQlh3BDt9NUlK1ELXkM7cnj2HS7+/C0u/uZKtGMSm6udj5/ncdcerTfb06dvVNfeOm3XD7vRHz5d9psPz57/HvEMvpEdT4fN+Hg5jb304WtZ+3mb2rGbUrnrH0Wnh3WVKNxd+7//Bw==", "file_map": { "16": { "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the\n// underlying proof system.\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n let mut result = embedded_curve_add_unsafe(point1_1, point2_1);\n\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n let double = embedded_curve_add_unsafe(point1, point1);\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n result = if double_predicate { double } else { result };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n // Ensure is_infinite is comptime\n let point1_1 = EmbeddedCurvePoint { x: point1.x, y: point1.y, is_infinite: false };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n embedded_curve_add_unsafe(point1_1, point2_1)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2)[0]\n}\n", diff --git a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_9223372036854775807.snap b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_9223372036854775807.snap index 3ebd817e856..706aeb57026 100644 --- a/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_9223372036854775807.snap +++ b/tooling/nargo_cli/tests/snapshots/execution_success/embedded_curve_ops/execute__tests__force_brillig_true_inliner_9223372036854775807.snap @@ -31,6 +31,10 @@ expression: artifact ], "return_type": null, "error_types": { + "12049594436772143978": { + "error_kind": "string", + "string": "array ref-count underflow detected" + }, "17843811134343075018": { "error_kind": "string", "string": "Stack too deep" @@ -45,9 +49,9 @@ expression: artifact "return value indices : []", "BRILLIG CALL func 0: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(1))], q_c: 0 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })], outputs: []", "unconstrained func 0", - "[Const { destination: Direct(2), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(1), bit_size: Integer(U32), value: 32839 }, Const { destination: Direct(0), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(4), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(5), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(32836), size_address: Relative(4), offset_address: Relative(5) }, Mov { destination: Relative(1), source: Direct(32836) }, Mov { destination: Relative(2), source: Direct(32837) }, Mov { destination: Relative(3), source: Direct(32838) }, Call { location: 14 }, Call { location: 15 }, Const { destination: Relative(1), bit_size: Integer(U32), value: 32839 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Stop { return_data: HeapVector { pointer: Relative(1), size: Relative(2) } }, Return, Call { location: 349 }, Const { destination: Relative(4), bit_size: Field, value: 1 }, Const { destination: Relative(5), bit_size: Field, value: 17631683881184975370165255887551781615748388533673675138860 }, Const { destination: Relative(6), bit_size: Integer(U1), value: 0 }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Mov { destination: Relative(9), source: Relative(8) }, Store { destination_pointer: Relative(9), source: Relative(4) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(5) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(6) }, Const { destination: Relative(8), bit_size: Field, value: 0 }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Mov { destination: Relative(11), source: Relative(10) }, Store { destination_pointer: Relative(11), source: Relative(1) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Store { destination_pointer: Relative(11), source: Relative(8) }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(11), size: Relative(12) }, scalars: HeapVector { pointer: Relative(13), size: Relative(14) }, outputs: HeapArray { pointer: Relative(15), size: 3 } }), Const { destination: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(7) }, Load { destination: Relative(9), source_pointer: Relative(11) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(11) }, Load { destination: Relative(12), source_pointer: Relative(13) }, BinaryFieldOp { destination: Relative(10), op: Equals, lhs: Relative(9), rhs: Relative(2) }, JumpIf { condition: Relative(10), location: 60 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, BinaryFieldOp { destination: Relative(9), op: Equals, lhs: Relative(12), rhs: Relative(3) }, JumpIf { condition: Relative(9), location: 64 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(2), input1_y: Relative(3), input1_infinite: Relative(6), input2_x: Relative(2), input2_y: Relative(3), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(10), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(9), rhs: Relative(7) }, Load { destination: Relative(10), source_pointer: Relative(12) }, Const { destination: Relative(9), bit_size: Field, value: 3078034153852398078128400807926804309327113743808504829582559963737223069694 }, BinaryFieldOp { destination: Relative(12), op: Equals, lhs: Relative(9), rhs: Relative(10) }, JumpIf { condition: Relative(12), location: 77 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 7 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(12) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, Mov { destination: Relative(13), source: Relative(12) }, Store { destination_pointer: Relative(13), source: Relative(4) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(5) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(6) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(4) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(5) }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Store { destination_pointer: Relative(13), source: Relative(6) }, Mov { destination: Relative(12), source: Direct(1) }, Const { destination: Relative(13), bit_size: Integer(U32), value: 5 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(13) }, IndirectConst { destination_pointer: Relative(12), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Mov { destination: Relative(14), source: Relative(13) }, Store { destination_pointer: Relative(14), source: Relative(1) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(8) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(1) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(8) }, Mov { destination: Relative(13), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(13), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, Const { destination: Relative(15), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Const { destination: Relative(17), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(14), size: Relative(15) }, scalars: HeapVector { pointer: Relative(16), size: Relative(17) }, outputs: HeapArray { pointer: Relative(18), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(13), rhs: Relative(7) }, Load { destination: Relative(10), source_pointer: Relative(12) }, BinaryFieldOp { destination: Relative(12), op: Equals, lhs: Relative(9), rhs: Relative(10) }, JumpIf { condition: Relative(12), location: 123 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 7 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Mov { destination: Relative(12), source: Relative(10) }, Store { destination_pointer: Relative(12), source: Relative(1) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(8) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(1) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(8) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(4) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(8) }, Const { destination: Relative(10), bit_size: Field, value: 11179562631109628533987091031692370366552561688588090155835439555627259799605 }, Const { destination: Relative(12), bit_size: Field, value: 3443719903172018228650470536370404288991794296383447657609081676265727805364 }, Mov { destination: Relative(13), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 10 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(13), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Mov { destination: Relative(15), source: Relative(14) }, Store { destination_pointer: Relative(15), source: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(5) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(2) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(3) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(10) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(12) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(12) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 9 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Const { destination: Relative(16), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(12), size: Relative(14) }, scalars: HeapVector { pointer: Relative(15), size: Relative(16) }, outputs: HeapArray { pointer: Relative(17), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(7) }, Load { destination: Relative(9), source_pointer: Relative(12) }, Const { destination: Relative(10), bit_size: Field, value: -7349266043899242844836273743257843180744506495159104166319746739537754653274 }, BinaryFieldOp { destination: Relative(12), op: Equals, lhs: Relative(9), rhs: Relative(10) }, JumpIf { condition: Relative(12), location: 182 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Mov { destination: Relative(12), source: Relative(10) }, Store { destination_pointer: Relative(12), source: Relative(1) }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Store { destination_pointer: Relative(12), source: Relative(8) }, Mov { destination: Relative(1), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(1), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Mov { destination: Relative(10), source: Relative(8) }, Store { destination_pointer: Relative(10), source: Relative(4) }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, Store { destination_pointer: Relative(10), source: Relative(5) }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, Store { destination_pointer: Relative(10), source: Relative(6) }, Mov { destination: Relative(8), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(8), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(10), size: Relative(12) }, scalars: HeapVector { pointer: Relative(13), size: Relative(14) }, outputs: HeapArray { pointer: Relative(15), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(7) }, Load { destination: Relative(1), source_pointer: Relative(9) }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(11) }, Load { destination: Relative(9), source_pointer: Relative(10) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(10) }, Load { destination: Relative(11), source_pointer: Relative(12) }, BinaryIntOp { destination: Relative(8), op: Equals, bit_size: U1, lhs: Relative(11), rhs: Relative(6) }, JumpIf { condition: Relative(8), location: 223 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(1), rhs: Relative(4) }, JumpIf { condition: Relative(8), location: 227 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(9), rhs: Relative(5) }, JumpIf { condition: Relative(1), location: 231 }, Const { destination: Relative(8), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(8) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(2), rhs: Relative(3) }, JumpIf { condition: Relative(1), location: 234 }, Jump { location: 348 }, Const { destination: Relative(1), bit_size: Field, value: 2 }, Mov { destination: Relative(5), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(5), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(5), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(4), input1_y: Relative(1), input1_infinite: Relative(6), input2_x: Relative(4), input2_y: Relative(1), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(8), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(5), rhs: Relative(7) }, Load { destination: Relative(8), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(5), op: Equals, lhs: Relative(8), rhs: Relative(4) }, JumpIf { condition: Relative(5), location: 247 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Const { destination: Relative(5), bit_size: Field, value: 3 }, Mov { destination: Relative(8), source: Direct(1) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(9) }, IndirectConst { destination_pointer: Relative(8), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(4), input1_y: Relative(1), input1_infinite: Relative(6), input2_x: Relative(4), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(9), size: 3 } }), BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(7) }, Load { destination: Relative(9), source_pointer: Relative(10) }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(9), rhs: Relative(4) }, JumpIf { condition: Relative(8), location: 260 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, BinaryFieldOp { destination: Relative(8), op: Add, lhs: Relative(2), rhs: Relative(4) }, BinaryFieldOp { destination: Relative(9), op: Add, lhs: Relative(3), rhs: Relative(4) }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(8), input1_y: Relative(3), input1_infinite: Relative(6), input2_x: Relative(8), input2_y: Relative(3), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(11), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(7) }, Load { destination: Relative(11), source_pointer: Relative(12) }, BinaryFieldOp { destination: Relative(10), op: Equals, lhs: Relative(11), rhs: Relative(4) }, JumpIf { condition: Relative(10), location: 274 }, Const { destination: Relative(12), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(12) } }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(8), input1_y: Relative(3), input1_infinite: Relative(6), input2_x: Relative(8), input2_y: Relative(9), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(11), size: 3 } }), BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(7) }, Load { destination: Relative(3), source_pointer: Relative(8) }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(3), rhs: Relative(4) }, JumpIf { condition: Relative(8), location: 286 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(2), input2_y: Relative(9), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(8), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(3), rhs: Relative(7) }, Load { destination: Relative(8), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(3), op: Equals, lhs: Relative(8), rhs: Relative(4) }, JumpIf { condition: Relative(3), location: 298 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Const { destination: Relative(3), bit_size: Field, value: 4 }, Mov { destination: Relative(8), source: Direct(1) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(9) }, IndirectConst { destination_pointer: Relative(8), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(8), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(1), input2_y: Relative(3), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(9), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(8), rhs: Relative(7) }, Load { destination: Relative(3), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(8), op: Equals, lhs: Relative(3), rhs: Relative(4) }, JumpIf { condition: Relative(8), location: 311 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(1), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(1), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(8), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(3), rhs: Relative(7) }, Load { destination: Relative(8), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(3), op: Equals, lhs: Relative(8), rhs: Relative(4) }, JumpIf { condition: Relative(3), location: 323 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(4), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(4), input2_y: Relative(5), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(8), size: 3 } }), BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(3), rhs: Relative(7) }, Load { destination: Relative(8), source_pointer: Relative(9) }, BinaryFieldOp { destination: Relative(3), op: Equals, lhs: Relative(8), rhs: Relative(4) }, JumpIf { condition: Relative(3), location: 335 }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(9) } }, Mov { destination: Relative(3), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(3), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(3), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(2), input1_y: Relative(5), input1_infinite: Relative(6), input2_x: Relative(2), input2_y: Relative(1), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(8), size: 3 } }), BinaryIntOp { destination: Relative(2), op: Add, bit_size: U32, lhs: Relative(3), rhs: Relative(7) }, Load { destination: Relative(1), source_pointer: Relative(2) }, BinaryFieldOp { destination: Relative(2), op: Equals, lhs: Relative(1), rhs: Relative(4) }, JumpIf { condition: Relative(2), location: 347 }, Const { destination: Relative(3), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(3) } }, Jump { location: 348 }, Return, Const { destination: Direct(32772), bit_size: Integer(U32), value: 30720 }, BinaryIntOp { destination: Direct(32771), op: LessThan, bit_size: U32, lhs: Direct(0), rhs: Direct(32772) }, JumpIf { condition: Direct(32771), location: 354 }, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 17843811134343075018 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return]" + "[Const { destination: Direct(2), bit_size: Integer(U32), value: 1 }, Const { destination: Direct(1), bit_size: Integer(U32), value: 32839 }, Const { destination: Direct(0), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(4), bit_size: Integer(U32), value: 3 }, Const { destination: Relative(5), bit_size: Integer(U32), value: 0 }, CalldataCopy { destination_address: Direct(32836), size_address: Relative(4), offset_address: Relative(5) }, Mov { destination: Relative(1), source: Direct(32836) }, Mov { destination: Relative(2), source: Direct(32837) }, Mov { destination: Relative(3), source: Direct(32838) }, Call { location: 14 }, Call { location: 15 }, Const { destination: Relative(1), bit_size: Integer(U32), value: 32839 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Stop { return_data: HeapVector { pointer: Relative(1), size: Relative(2) } }, Return, Call { location: 222 }, Const { destination: Relative(4), bit_size: Field, value: 1 }, Const { destination: Relative(5), bit_size: Field, value: 17631683881184975370165255887551781615748388533673675138860 }, Const { destination: Relative(6), bit_size: Integer(U1), value: 0 }, Mov { destination: Relative(7), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(7), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Mov { destination: Relative(9), source: Relative(8) }, Store { destination_pointer: Relative(9), source: Relative(4) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(5) }, BinaryIntOp { destination: Relative(9), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(6) }, Const { destination: Relative(8), bit_size: Field, value: 0 }, Mov { destination: Relative(9), source: Direct(1) }, Const { destination: Relative(10), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(10) }, IndirectConst { destination_pointer: Relative(9), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(10), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Mov { destination: Relative(11), source: Relative(10) }, Store { destination_pointer: Relative(11), source: Relative(1) }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(11), rhs: Direct(2) }, Store { destination_pointer: Relative(11), source: Relative(8) }, Mov { destination: Relative(10), source: Direct(1) }, Const { destination: Relative(11), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(11) }, IndirectConst { destination_pointer: Relative(10), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(11), op: Add, bit_size: U32, lhs: Relative(7), rhs: Direct(2) }, Const { destination: Relative(12), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(9), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(10), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(11), size: Relative(12) }, scalars: HeapVector { pointer: Relative(13), size: Relative(14) }, outputs: HeapArray { pointer: Relative(15), size: 3 } }), Const { destination: Relative(11), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(11) }, Load { destination: Relative(12), source_pointer: Relative(13) }, Const { destination: Relative(13), bit_size: Integer(U32), value: 2 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(13) }, Load { destination: Relative(14), source_pointer: Relative(15) }, BinaryFieldOp { destination: Relative(13), op: Equals, lhs: Relative(12), rhs: Relative(2) }, JumpIf { condition: Relative(13), location: 60 }, Const { destination: Relative(15), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(15) } }, BinaryFieldOp { destination: Relative(12), op: Equals, lhs: Relative(14), rhs: Relative(3) }, JumpIf { condition: Relative(12), location: 64 }, Const { destination: Relative(13), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(13) } }, Mov { destination: Relative(12), source: Direct(1) }, Const { destination: Relative(13), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(13) }, IndirectConst { destination_pointer: Relative(12), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, BlackBox(EmbeddedCurveAdd { input1_x: Relative(2), input1_y: Relative(3), input1_infinite: Relative(6), input2_x: Relative(2), input2_y: Relative(3), input2_infinite: Relative(6), result: HeapArray { pointer: Relative(13), size: 3 } }), BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(12), rhs: Relative(11) }, Load { destination: Relative(13), source_pointer: Relative(14) }, Const { destination: Relative(12), bit_size: Field, value: 3078034153852398078128400807926804309327113743808504829582559963737223069694 }, BinaryFieldOp { destination: Relative(14), op: Equals, lhs: Relative(12), rhs: Relative(13) }, JumpIf { condition: Relative(14), location: 77 }, Const { destination: Relative(15), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(15) } }, Mov { destination: Relative(13), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 7 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(13), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Mov { destination: Relative(15), source: Relative(14) }, Store { destination_pointer: Relative(15), source: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(5) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(5) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, Mov { destination: Relative(14), source: Direct(1) }, Const { destination: Relative(15), bit_size: Integer(U32), value: 5 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(15) }, IndirectConst { destination_pointer: Relative(14), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Mov { destination: Relative(16), source: Relative(15) }, Store { destination_pointer: Relative(16), source: Relative(1) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(8) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(1) }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(16), rhs: Direct(2) }, Store { destination_pointer: Relative(16), source: Relative(8) }, Mov { destination: Relative(15), source: Direct(1) }, Const { destination: Relative(16), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(16) }, IndirectConst { destination_pointer: Relative(15), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(16), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Const { destination: Relative(17), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(18), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Const { destination: Relative(19), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Relative(20), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(16), size: Relative(17) }, scalars: HeapVector { pointer: Relative(18), size: Relative(19) }, outputs: HeapArray { pointer: Relative(20), size: 3 } }), BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(15), rhs: Relative(11) }, Load { destination: Relative(13), source_pointer: Relative(14) }, BinaryFieldOp { destination: Relative(14), op: Equals, lhs: Relative(12), rhs: Relative(13) }, JumpIf { condition: Relative(14), location: 123 }, Const { destination: Relative(15), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(15) } }, Mov { destination: Relative(12), source: Direct(1) }, Const { destination: Relative(13), bit_size: Integer(U32), value: 7 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(13) }, IndirectConst { destination_pointer: Relative(12), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(13), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Mov { destination: Relative(14), source: Relative(13) }, Store { destination_pointer: Relative(14), source: Relative(1) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(8) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(1) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(8) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(4) }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(14), rhs: Direct(2) }, Store { destination_pointer: Relative(14), source: Relative(8) }, Const { destination: Relative(1), bit_size: Field, value: 11179562631109628533987091031692370366552561688588090155835439555627259799605 }, Const { destination: Relative(8), bit_size: Field, value: 3443719903172018228650470536370404288991794296383447657609081676265727805364 }, Mov { destination: Relative(13), source: Direct(1) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 10 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(14) }, IndirectConst { destination_pointer: Relative(13), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(14), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Mov { destination: Relative(15), source: Relative(14) }, Store { destination_pointer: Relative(15), source: Relative(4) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(5) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(2) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(3) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(1) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(8) }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(15), rhs: Direct(2) }, Store { destination_pointer: Relative(15), source: Relative(6) }, Mov { destination: Relative(1), source: Direct(1) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 4 }, BinaryIntOp { destination: Direct(1), op: Add, bit_size: U32, lhs: Direct(1), rhs: Relative(8) }, IndirectConst { destination_pointer: Relative(1), bit_size: Integer(U32), value: 1 }, BinaryIntOp { destination: Relative(8), op: Add, bit_size: U32, lhs: Relative(13), rhs: Direct(2) }, Const { destination: Relative(14), bit_size: Integer(U32), value: 9 }, BinaryIntOp { destination: Relative(15), op: Add, bit_size: U32, lhs: Relative(12), rhs: Direct(2) }, Const { destination: Relative(16), bit_size: Integer(U32), value: 6 }, BinaryIntOp { destination: Relative(17), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, BlackBox(MultiScalarMul { points: HeapVector { pointer: Relative(8), size: Relative(14) }, scalars: HeapVector { pointer: Relative(15), size: Relative(16) }, outputs: HeapArray { pointer: Relative(17), size: 3 } }), BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(1), rhs: Relative(11) }, Load { destination: Relative(8), source_pointer: Relative(12) }, Const { destination: Relative(1), bit_size: Field, value: -7349266043899242844836273743257843180744506495159104166319746739537754653274 }, BinaryFieldOp { destination: Relative(11), op: Equals, lhs: Relative(8), rhs: Relative(1) }, JumpIf { condition: Relative(11), location: 182 }, Const { destination: Relative(12), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(12) } }, Load { destination: Relative(1), source_pointer: Relative(9) }, Const { destination: Relative(8), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(11), op: Equals, bit_size: U32, lhs: Relative(8), rhs: Relative(1) }, Not { destination: Relative(11), source: Relative(11), bit_size: U1 }, JumpIf { condition: Relative(11), location: 188 }, Call { location: 228 }, BinaryIntOp { destination: Relative(1), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Store { destination_pointer: Relative(9), source: Relative(1) }, Load { destination: Relative(1), source_pointer: Relative(7) }, Const { destination: Relative(9), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(11), op: Equals, bit_size: U32, lhs: Relative(9), rhs: Relative(1) }, Not { destination: Relative(11), source: Relative(11), bit_size: U1 }, JumpIf { condition: Relative(11), location: 196 }, Call { location: 228 }, BinaryIntOp { destination: Relative(1), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Store { destination_pointer: Relative(7), source: Relative(1) }, Load { destination: Relative(1), source_pointer: Relative(10) }, Const { destination: Relative(7), bit_size: Integer(U32), value: 0 }, BinaryIntOp { destination: Relative(11), op: Equals, bit_size: U32, lhs: Relative(7), rhs: Relative(1) }, Not { destination: Relative(11), source: Relative(11), bit_size: U1 }, JumpIf { condition: Relative(11), location: 204 }, Call { location: 228 }, BinaryIntOp { destination: Relative(1), op: Add, bit_size: U32, lhs: Relative(1), rhs: Direct(2) }, Store { destination_pointer: Relative(10), source: Relative(1) }, Const { destination: Relative(1), bit_size: Integer(U32), value: 3 }, BinaryIntOp { destination: Relative(12), op: Add, bit_size: U32, lhs: Relative(10), rhs: Relative(1) }, Load { destination: Relative(11), source_pointer: Relative(12) }, BinaryIntOp { destination: Relative(1), op: Equals, bit_size: U1, lhs: Relative(11), rhs: Relative(6) }, JumpIf { condition: Relative(1), location: 213 }, Const { destination: Relative(10), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(10) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(2), rhs: Relative(4) }, JumpIf { condition: Relative(1), location: 217 }, Const { destination: Relative(6), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(6) } }, BinaryFieldOp { destination: Relative(1), op: Equals, lhs: Relative(3), rhs: Relative(5) }, JumpIf { condition: Relative(1), location: 221 }, Const { destination: Relative(2), bit_size: Integer(U32), value: 0 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Relative(2) } }, Return, Const { destination: Direct(32772), bit_size: Integer(U32), value: 30720 }, BinaryIntOp { destination: Direct(32771), op: LessThan, bit_size: U32, lhs: Direct(0), rhs: Direct(32772) }, JumpIf { condition: Direct(32771), location: 227 }, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 17843811134343075018 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return, IndirectConst { destination_pointer: Direct(1), bit_size: Integer(U64), value: 12049594436772143978 }, Trap { revert_data: HeapVector { pointer: Direct(1), size: Direct(2) } }, Return]" ], - "debug_symbols": "tZndThs9EIbvJccc2J4f29xKVaEAoYoUBZTCJ31C3Htndvwm9GBR2SQnfR9K/TT2euxZ5X31uLl/+3W33T89/17d/nhf3R+2u932193u+WH9un3e29++r5L/kXV1m29WuUa0iD5FSRE5okRQBEdIRFhKWEpYSlgoLBQWCguFhcJCYaGwUFgoLBQWNgtZ5IgSQREcIREaUSNaRJ9CzMIWOaJEUARHSIRZxKJGtIg+hZpFLXJEiaAIn1GylJE6so5sI3tk9dWx+dU80tenWNJIHikjdWQd2Ub2yJZG5pHD14avDV8bvjZ8bfja8LXh68PXh68PXx++Pnx9+Prw9eHrw9eHL6cEyIACIAADBKAA97JDA/QBOQEyoAAIwAABKMDN4tAAbrZnmqdCmCADCsDNzYEBAlBABTRAHzAVxwQZUAAwE8wEM8FMMBPMBDPDzDAzzAwzw8wwM8wMM8PMMAvMArPALDALzAKzwCwwC8wCs8KsMCvMCrPCrDArzAqzwqwwV5grzBXmCnOFeaq17qAAM5fk0AB9gBdcQAaYufhe9ZoLYIAAFFABDdAHeOkFZADMHeYOc4e5w9xh7jD3YS4pATKgAAjAAAEooAIaAOYMc4bZa7CQAwEYIAAFVEADuJn99kmADCgAAjBAAAqogAaAmWD2Gizi4J7uIAAFVEAD9AFecQF+SSWHAvCLaro1GSAABfiF5VOerqwJ+gCvuIAMKAACuNln4RUX4GafjldcQAP0AV5xpA5urg5+KU5XOgEYIAAFVICZ2R+3V9wEXnHsH8wrLqAACOBm/xhecQEKqIAG6AO84tg/s1dcgJv9w3vFBTBAAG72p+MVF9AAfYBXXEAGmFn8CXrFBZhZpu5GAAqoAG8XfIJecQ7kFReQAQVAAAa4mR0U4GZxaIA+wCsuwM3VoQAIwAABKMDNzaEB3Ny9U0uADCgAb3ambo4BAlBABTSAmbV485cA3kL5lP3WCyAAA9zsE/QaDKiABugDvAYD3KwOBeBmn7LXYIAA3Fw/Pm5WaJDvXg+bjffHnzpm66Nf1ofN/nV1u3/b7W5W/613b9M/+v2y3k/5uj7Yb22bbPaPliZ82u42Th83p9Fpfqjt1zHYNuxxuPzzeKp5jOfS5saX+fEsnSFQPk0g6zIDzRm+mAPzcQ4iC9aAtWN8owXjteMZ1Jznxtcvxhd8fpU8N//2xfjEmICmPvsM+rzBGt9Uh8JY+AKOuuBJVlGsZF3yJJpiJTulufGZzt7O/65Ysp/tdYawkEnTgnWwPv9oEJpdyVzPX4l61ZUQxoawzr4vWYlW8RmsneXZEy6ff8Tla66EteAoLuu9ecFKWGONe8Za60UGEszC+tvZXVX0zKOu1LPPutIucNh9R7LktLNXgnJcz16XPBH2988wsMzePVQusBrfkSxaDdbTXGpbshqixx0uuuS0sBeMo6HyIkPLxzptZbYjo3ZmjVA/u0Y4XWBXfEeyaFc0/tTgpkVPpGE97TVt9txjvsRq8JVXo9NpLpyX9PuloDOwV7DZ/cmXOD/5yuenvTGe5rKocyfuqBQSKnMGucT5KVc+P+1yPs1FlpxdVCtqjVqaPYFFL7EaeuXVaOU0F1r0VpgEdwGn+d2llzhF9cqnKNu3KJiLfe2xZDWIUGtMOntu6CVOUb3yKcq2I45z6X8/2Z/20/phe/jrm88Pdx226/vdZvz49LZ/+PTb1/9f8Bt8c/pyeH7YPL4dNm769PWp/fnDjp0bK9efH/7//QE=", + "debug_symbols": "tZffTioxEIffZa+5aDszbcdXMcYgroaEAEE4yYnh3U+7Mz//XKwx6/HG70PsJ+1uKbwOj+PD5fl+u386vAw3t6/Dw2m7222f73eHzfq8Pezbb1+H0H/EPNzE1RCLoRp0QgqGaEgGMrBBDFZJVklWSVYhq5BVyCpkFbIKWYWsQlYhq5BVuFWoIRqSgQxsEEM2FEM16ARpFW6IhmQgAxvE0CrSUAzVoBNyq+SGaEgGMvQZhUZxZmdxVqcaS1+dNr8SnX19UiM52SnO7CzO6lRjDc7o9F71XvVe9V71XvVe9V71nnpPvafeU++p99R76j31nnpPvRdDgERIghCEIQLJkN7lLhWiLjFAIiRBCMIQgWRIL0uXCunldk3jtBEmiZAE6eXahSECyZACqRB1mTbHJBGSICgTyoQyoUwoE8qEMqPMKDPKjDKjzCgzyowyo8woC8qCsqAsKAvKgrKgLCgLyoJyRjmjnFHOKGeUM8oZ5YxyRjmjXFAuKBeUC8oF5WmvaZcMaeUUulSIuvQNZxIhrZz6vdr3nAlDBJIhBVIh6tK3nkmEoKwoK8qKsqKsKCvK6uUUAiRCEoQgDBFIL1OXAqmQXuZ+VARIhCQIQRgikAwpkApBOU3l63U14BC7P5/GsZ9hH061dtYd16dxfx5u9pfdbjX8We8u0x+9HNf7ief1qT3bLtS4f2xswaftbux2Xb2PDvNDUxUfnGp+Gy7fHk8l+nhOdW58mh/PooxA5vcJxLysQHOFL+bA/DYHkQVrwFkxvtKC8VlxDUqMc+PLF+MTXn+WODf/+sX4wJhADjp7DXS+0A6nUDzRXPg/NMqCK1kkYyXLkitRM1ZSKcyNj/Tj2/n7iSX3c/vIQVjIkMOCdWhn8VtBaHYlY/n5SpRfXQlh3BDt9NUlK1ELXkM7cnj2HS7+/C0u/uZKtGMSm6udj5/ncdcerTfb06dvVNfeOm3XD7vRHz5d9psPz57/HvEMvpEdT4fN+Hg5jb304WtZ+3mb2rGbUrnrH0Wnh3WVKNxd+7//Bw==", "file_map": { "16": { "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the\n// underlying proof system.\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n let mut result = embedded_curve_add_unsafe(point1_1, point2_1);\n\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n let double = embedded_curve_add_unsafe(point1, point1);\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n result = if double_predicate { double } else { result };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n // Ensure is_infinite is comptime\n let point1_1 = EmbeddedCurvePoint { x: point1.x, y: point1.y, is_infinite: false };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n embedded_curve_add_unsafe(point1_1, point2_1)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2)[0]\n}\n",