use crate::{
FieldElement,
circuit::{Circuit, Program, brillig::BrilligBytecode},
native_types::Witness,
};
use brillig::{
BitSize, HeapArray, HeapValueType, HeapVector, IntegerBitSize, MemoryAddress, ValueOrArray,
lengths::{SemanticLength, SemiFlattenedLength},
};
pub fn addition_program() -> Program<FieldElement> {
let src = "
private parameters: [w1, w2]
public parameters: []
return values: [w3]
ASSERT 0 = w1 + w2 - w3
";
let circuit = Circuit::from_str(src).unwrap();
Program { functions: vec![circuit], unconstrained_functions: vec![] }
}
pub fn multi_scalar_mul_program() -> Program<FieldElement> {
let src = "
private parameters: [w1, w2, w3, w4, w5]
public parameters: []
return values: [w6, w7]
BLACKBOX::MULTI_SCALAR_MUL points: [w1, w2], scalars: [w3, w4], predicate: w5, outputs: [w6, w7]
";
let circuit = Circuit::from_str(src).unwrap();
Program { functions: vec![circuit], unconstrained_functions: vec![] }
}
pub fn simple_brillig_foreign_call_program() -> Program<FieldElement> {
let w_input = Witness(1);
let w_inverted = Witness(2);
let value_address = MemoryAddress::direct(0);
let zero_usize = MemoryAddress::direct(1);
let one_usize = MemoryAddress::direct(2);
let brillig_bytecode = BrilligBytecode {
function_name: "invert_call".into(),
bytecode: vec![
brillig::Opcode::Const {
destination: zero_usize,
bit_size: BitSize::Integer(IntegerBitSize::U32),
value: FieldElement::from(0_usize),
},
brillig::Opcode::Const {
destination: one_usize,
bit_size: BitSize::Integer(IntegerBitSize::U32),
value: FieldElement::from(1_usize),
},
brillig::Opcode::CalldataCopy {
destination_address: value_address,
size_address: one_usize,
offset_address: zero_usize,
},
brillig::Opcode::ForeignCall {
function: "invert".into(),
destinations: vec![ValueOrArray::MemoryAddress(value_address)],
destination_value_types: vec![HeapValueType::field()],
inputs: vec![ValueOrArray::MemoryAddress(value_address)],
input_value_types: vec![HeapValueType::field()],
},
brillig::Opcode::Stop {
return_data: HeapVector { pointer: zero_usize, size: one_usize },
},
],
};
let src = format!(
"
private parameters: [{w_input}, {w_inverted}]
public parameters: []
return values: []
BRILLIG CALL func: 0, predicate: 1, inputs: [{w_input}], outputs: [{w_inverted}]
"
);
let circuit = Circuit::from_str(&src).unwrap();
Program { functions: vec![circuit], unconstrained_functions: vec![brillig_bytecode] }
}
pub fn complex_brillig_foreign_call_program() -> Program<FieldElement> {
let a = Witness(1);
let b = Witness(2);
let c = Witness(3);
let a_times_2 = Witness(4);
let b_times_3 = Witness(5);
let c_times_4 = Witness(6);
let a_plus_b_plus_c = Witness(7);
let a_plus_b_plus_c_times_2 = Witness(8);
let brillig_bytecode = BrilligBytecode {
function_name: "complex_call".into(),
bytecode: vec![
brillig::Opcode::Const {
destination: MemoryAddress::direct(0),
bit_size: BitSize::Integer(IntegerBitSize::U32),
value: FieldElement::from(3_usize),
},
brillig::Opcode::Const {
destination: MemoryAddress::direct(1),
bit_size: BitSize::Integer(IntegerBitSize::U32),
value: FieldElement::from(0_usize),
},
brillig::Opcode::CalldataCopy {
destination_address: MemoryAddress::direct(32),
size_address: MemoryAddress::direct(0),
offset_address: MemoryAddress::direct(1),
},
brillig::Opcode::Const {
destination: MemoryAddress::direct(0),
value: FieldElement::from(32_usize),
bit_size: BitSize::Integer(IntegerBitSize::U32),
},
brillig::Opcode::Const {
destination: MemoryAddress::direct(3),
bit_size: BitSize::Integer(IntegerBitSize::U32),
value: FieldElement::from(1_usize),
},
brillig::Opcode::Const {
destination: MemoryAddress::direct(4),
bit_size: BitSize::Integer(IntegerBitSize::U32),
value: FieldElement::from(3_usize),
},
brillig::Opcode::CalldataCopy {
destination_address: MemoryAddress::direct(1),
size_address: MemoryAddress::direct(3),
offset_address: MemoryAddress::direct(4),
},
brillig::Opcode::ForeignCall {
function: "complex".into(),
inputs: vec![
ValueOrArray::HeapArray(HeapArray {
pointer: MemoryAddress::direct(0),
size: SemiFlattenedLength(3),
}),
ValueOrArray::MemoryAddress(MemoryAddress::direct(1)),
],
input_value_types: vec![
HeapValueType::Array {
size: SemanticLength(3),
value_types: vec![HeapValueType::field()],
},
HeapValueType::field(),
],
destinations: vec![
ValueOrArray::HeapArray(HeapArray {
pointer: MemoryAddress::direct(0),
size: SemiFlattenedLength(3),
}),
ValueOrArray::MemoryAddress(MemoryAddress::direct(35)),
ValueOrArray::MemoryAddress(MemoryAddress::direct(36)),
],
destination_value_types: vec![
HeapValueType::Array {
size: SemanticLength(3),
value_types: vec![HeapValueType::field()],
},
HeapValueType::field(),
HeapValueType::field(),
],
},
brillig::Opcode::Const {
destination: MemoryAddress::direct(0),
bit_size: BitSize::Integer(IntegerBitSize::U32),
value: FieldElement::from(32_usize),
},
brillig::Opcode::Const {
destination: MemoryAddress::direct(1),
bit_size: BitSize::Integer(IntegerBitSize::U32),
value: FieldElement::from(5_usize),
},
brillig::Opcode::Stop {
return_data: HeapVector {
pointer: MemoryAddress::direct(0),
size: MemoryAddress::direct(1),
},
},
],
};
let src = format!("
private parameters: [{a}, {b}, {c}]
public parameters: []
return values: []
BRILLIG CALL func: 0, predicate: 1, inputs: [[{a}, {b}, {c}], {a} + {b} + {c}], outputs: [[{a_times_2}, {b_times_3}, {c_times_4}], {a_plus_b_plus_c}, {a_plus_b_plus_c_times_2}]
");
let circuit = Circuit::from_str(&src).unwrap();
Program { functions: vec![circuit], unconstrained_functions: vec![brillig_bytecode] }
}
pub fn memory_op_program() -> Program<FieldElement> {
let src = "
private parameters: [w1, w2, w3]
public parameters: []
return values: [w4]
INIT b0 = [w1, w2]
WRITE b0[w5] = w3
READ w4 = b0[w5]
";
let circuit = Circuit::from_str(src).unwrap();
Program { functions: vec![circuit], unconstrained_functions: vec![] }
}
pub fn nested_acir_call_program() -> Program<FieldElement> {
let src = "
private parameters: [w0]
public parameters: [w1]
return values: []
CALL func: 1, predicate: 1, inputs: [w0, w1], outputs: [w2]
CALL func: 1, predicate: 1, inputs: [w0, w1], outputs: [w3]
ASSERT 0 = w2 - w3
";
let main = Circuit::from_str(src).unwrap();
let src = "
private parameters: [w0, w1]
public parameters: []
return values: [w3]
ASSERT 0 = w0 - w2 + 2
CALL func: 2, predicate: 1, inputs: [w2, w1], outputs: [w3]
";
let nested_call = Circuit::from_str(src).unwrap();
let src = "
private parameters: [w0, w1]
public parameters: []
return values: [w0]
ASSERT 0 = w0 - w1
";
let inner_call = Circuit::from_str(src).unwrap();
Program { functions: vec![main, nested_call, inner_call], unconstrained_functions: vec![] }
}