Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions avm-transpiler/src/procedures/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,8 @@ fn compile_opcode(
Mnemonic::ECADD => {
collector.memory_address_operand()?; // p1 x
collector.memory_address_operand()?; // p1 y
collector.memory_address_operand()?; // p1 is_infinite
collector.memory_address_operand()?; // p2 x
collector.memory_address_operand()?; // p2 y
collector.memory_address_operand()?; // p2 is_infinite
collector.memory_address_operand()?; // result
let collection = collector.finish()?;
result.add_instruction(
Expand Down
24 changes: 9 additions & 15 deletions avm-transpiler/src/procedures/msm.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
pub(crate) const MSM_ASSEMBLY: &str = "
; We are passed three pointers and one usize.
; d0 points to the points. Points are represented by (x: Field, y: Field, is_infinite: bool)
; d0 points to the points. Points are represented by (x: Field, y: Field).
; d1 points to the scalars. Scalars are represented by (lo: Field, hi: Field) both range checked to 128 bits.
; d2 contains the number of points.
; d3 points to the result. The result is a point.
ADD d3, /*the reserved register 'one_usize'*/ $2, d4; Compute the pointer to the result y.
ADD d4, $2, d5; Compute the pointer to the result is_infinite
; Initialize the msm result: point at infinity
SET i3, 0 ff
SET i4, 0 ff
SET i5, 1 u1
; Loop globals
SET d6, 0 u32; Initialize the outer loop variable, ranging from 0 to the number of points
SET d8, 0 ff; Initialize a 0 FF
Expand All @@ -18,13 +16,12 @@ pub(crate) const MSM_ASSEMBLY: &str = "
SET d10, 128 u32; Initialize a constant 128
SET d11, 1 u1; Initialize a constant true
SET d12, 0 u1; Initialize a constant false
SET d13, 2 u32; Initialize a constant 2
SET d14, 3 u32; Initialize a constant 3 for computing pointers to the point components
SET d13, 2 u32; Initialize a constant 2 for computing pointers to point and scalar components
; Main loop: iterate over the points/scalars
OUTER_HEAD: LT d6, d2, d15 ; Check if we are done with the outer loop
JUMPI d15, OUTER_BODY
JUMP OUTER_END
OUTER_BODY: MUL d6, d14, d16; Compute the pointer to the point
OUTER_BODY: MUL d6, d13, d16; Compute the pointer to the point
ADD d16, d0, d16;
MUL d6, d13, d17; Compute the pointer to the scalar lo
ADD d17, d1, d17
Expand All @@ -51,35 +48,32 @@ FIND_MSB_BODY: JUMPI i19, FIND_MSB_END; Check if the current bit is one
JUMP FIND_MSB_BODY
; Now we have the pointer of the MSB in d19

; Now store the result of the scalar multiplication in d22, d23, d24
; Now store the result of the scalar multiplication in d22, d23
FIND_MSB_END: MOV i16, d22; x
ADD d16, $2, d25; pointer to y
MOV i25, d23; y
ADD d25, $2, d25; pointer to is_infinite
MOV i25, d24; is_infinite
; Also store the original point in d25, d26, d27
; Also store the original point in d25, d26
MOV d22, d25; x
MOV d23, d26; y
MOV d24, d27; is_infinite

; Now we need to do the inner loop, that will do double then add
; We need to iterate from the pointer of the MSB + 1 to the end pointer (d21)
ADD d19, $2, d19; We start from the pointer of the MSB + 1
INNER_HEAD: LT d19, d21, d28; Check if we are done with the loop
JUMPI d28, INNER_BODY
JUMP INNER_END
INNER_BODY: ECADD d22, d23, d24, d22, d23, d24, /*not indirect, so the result is stored in d22, d23, d24*/ d22; Double the current result.
INNER_BODY: ECADD d22, d23, d22, d23, /*not indirect, so the result is stored in d22, d23*/ d22; Double the current result.
EQ i19, d12, d28; Check if the current bit is zero
JUMPI d28, INNER_INC; If the current bit is zero, continue
ECADD d25, d26, d27, d22, d23, d24, /*not indirect, so the result is stored in d22, d23, d24*/ d22; Add the original point to the result
ECADD d25, d26, d22, d23, /*not indirect, so the result is stored in d22, d23*/ d22; Add the original point to the result
INNER_INC: ADD d19, $2, d19; Increment the pointer
JUMP INNER_HEAD

; After the inner loop we have computed the scalar multiplication. Add it to the msm result
INNER_END: ECADD i3, i4, i5, d22, d23, d24, i3; Add the result to the msm result
INNER_END: ECADD i3, i4, d22, d23, i3; Add the result to the msm result
OUTER_INC: ADD d6, $2, d6; Increment the outer loop variable
JUMP OUTER_HEAD
; After the outer loop we have computed the msm. We can return since we wrote the result in i3, i4, i5
; After the outer loop we have computed the msm. We can return since we wrote the result in i3, i4
OUTER_END: INTERNALRETURN
";

Expand Down
21 changes: 8 additions & 13 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,53 +1280,46 @@ fn handle_black_box_function(
BlackBoxOp::EmbeddedCurveAdd {
input1_x: p1_x_offset,
input1_y: p1_y_offset,
input1_infinite: p1_infinite_offset,
input2_x: p2_x_offset,
input2_y: p2_y_offset,
input2_infinite: p2_infinite_offset,
result,
} => avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::ECADD,
// The result (SIXTH operand) is indirect (addressing mode).
// The result (FOURTH operand) is indirect (addressing mode).
addressing_mode: Some(
AddressingModeBuilder::default()
.direct_operand(p1_x_offset)
.direct_operand(p1_y_offset)
.direct_operand(p1_infinite_offset)
.direct_operand(p2_x_offset)
.direct_operand(p2_y_offset)
.direct_operand(p2_infinite_offset)
.indirect_operand(&result.pointer)
.build(),
),
operands: vec![
AvmOperand::U16 { value: p1_x_offset.to_u32() as u16 },
AvmOperand::U16 { value: p1_y_offset.to_u32() as u16 },
AvmOperand::U16 { value: p1_infinite_offset.to_u32() as u16 },
AvmOperand::U16 { value: p2_x_offset.to_u32() as u16 },
AvmOperand::U16 { value: p2_y_offset.to_u32() as u16 },
AvmOperand::U16 { value: p2_infinite_offset.to_u32() as u16 },
AvmOperand::U16 { value: result.pointer.to_u32() as u16 },
],
..Default::default()
}),

BlackBoxOp::MultiScalarMul { points, scalars, outputs } => {
// The length of the scalars vector is 2x the length of the points vector due to limb
// decomposition
// Output array is fixed to 3
// decomposition. Points are (x, y); the point at infinity is encoded as (0, 0).
assert_eq!(
outputs.size,
SemiFlattenedLength(3),
"Output array size must be equal to 3"
SemiFlattenedLength(2),
"Output array size must be equal to 2"
);
assert_eq!(points.size.0 % 3, 0, "Points array size must be divisible by 3");
assert_eq!(points.size.0 % 2, 0, "Points array size must be divisible by 2");

avm_instrs.push(generate_mov_to_procedure(&points.pointer, 0));
avm_instrs.push(generate_mov_to_procedure(&scalars.pointer, 1));
avm_instrs.push(generate_set_to_procedure(
AvmTypeTag::UINT32,
&FieldElement::from(points.size.0 / 3),
&FieldElement::from(points.size.0 / 2),
2,
));
avm_instrs.push(generate_mov_to_procedure(&outputs.pointer, 3));
Expand Down Expand Up @@ -1634,6 +1627,7 @@ fn handle_get_contract_instance(
DEPLOYER,
CLASS_ID,
INIT_HASH,
IMMUTABLES_HASH,
}

assert_eq!(inputs.len(), 1);
Expand All @@ -1643,6 +1637,7 @@ fn handle_get_contract_instance(
"aztec_avm_getContractInstanceDeployer" => ContractInstanceMember::DEPLOYER,
"aztec_avm_getContractInstanceClassId" => ContractInstanceMember::CLASS_ID,
"aztec_avm_getContractInstanceInitializationHash" => ContractInstanceMember::INIT_HASH,
"aztec_avm_getContractInstanceImmutablesHash" => ContractInstanceMember::IMMUTABLES_HASH,
_ => panic!("Transpiler doesn't know how to process function {:?}", function),
};

Expand Down
Loading
Loading