Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(avm): brillig CONST of size > u128 #5217

Merged
merged 1 commit into from
Mar 15, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ impl Deserialize<2> for Note {

contract AvmTest {
use crate::Note;

global big_field_128_bits: Field = 0x001234567890abcdef1234567890abcdef;
global big_field_136_bits: Field = 0x991234567890abcdef1234567890abcdef;

// Libs
use dep::aztec::prelude::Map;
Expand Down Expand Up @@ -94,12 +97,6 @@ contract AvmTest {
8 as u8
}

// Bit size 16 in Noir is deprecated.
// #[aztec(public-vm)]
// fn setOpcodeUint16() -> pub u16 {
// 60000 as u16
// }

#[aztec(public-vm)]
fn setOpcodeUint32() -> pub u32 {
1 << 30 as u32
Expand All @@ -110,18 +107,14 @@ contract AvmTest {
1 << 60 as u64
}

// Can't return this since it doesn't fit in a Noir field.
// #[aztec(public-vm)]
// fn setOpcodeUint128() -> pub u128 {
// 1 << 120 as u128
// }

// Field should fit in 128 bits
// ACIR only supports fields of up to 126 bits!
// Same with internal fields for unconstrained functions, apprently.
#[aztec(public-vm)]
fn setOpcodeSmallField() -> pub Field {
200 as Field
big_field_128_bits
}

#[aztec(public-vm)]
fn setOpcodeBigField() -> pub Field {
big_field_136_bits
}

#[aztec(public-vm)]
Expand Down
52 changes: 47 additions & 5 deletions noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,11 +593,53 @@ impl BrilligContext {
pub(crate) fn const_instruction(&mut self, result: SingleAddrVariable, constant: Value) {
self.debug_show.const_instruction(result.address, constant);

self.push_opcode(BrilligOpcode::Const {
destination: result.address,
value: constant,
bit_size: result.bit_size,
});
if result.bit_size > 128 && !constant.to_field().fits_in_u128() {
let high = Value::from(FieldElement::from_be_bytes_reduce(
constant
.to_field()
.to_be_bytes()
.get(0..16)
.expect("FieldElement::to_be_bytes() too short!"),
));
let low = Value::from(constant.to_u128());
let high_register = SingleAddrVariable::new(self.allocate_register(), 254);
let low_register = SingleAddrVariable::new(self.allocate_register(), 254);
let intermediate_register = SingleAddrVariable::new(self.allocate_register(), 254);
self.const_instruction(high_register, high);
self.const_instruction(low_register, low);
// I want to multiply high by 2^128, but I can't get that big constant in.
// So I'll multiply by 2^64 twice.
self.const_instruction(intermediate_register, Value::from(1_u128 << 64));
self.binary_instruction(
high_register,
intermediate_register,
high_register,
BrilligBinaryOp::Mul,
);
self.binary_instruction(
high_register,
intermediate_register,
high_register,
BrilligBinaryOp::Mul,
);
// Now we can add.
self.binary_instruction(
high_register,
low_register,
intermediate_register,
BrilligBinaryOp::Add,
);
self.cast_instruction(result, intermediate_register);
self.deallocate_single_addr(high_register);
self.deallocate_single_addr(low_register);
self.deallocate_single_addr(intermediate_register);
} else {
self.push_opcode(BrilligOpcode::Const {
destination: result.address,
value: constant,
bit_size: result.bit_size,
});
}
}

pub(crate) fn usize_const(&mut self, result: MemoryAddress, constant: Value) {
Expand Down
5 changes: 2 additions & 3 deletions yarn-project/simulator/src/avm/avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,10 @@ describe('AVM simulator', () => {

describe.each([
['avm_setOpcodeUint8', 8n],
// ['avm_setOpcodeUint16', 60000n],
['avm_setOpcodeUint32', 1n << 30n],
['avm_setOpcodeUint64', 1n << 60n],
// ['avm_setOpcodeUint128', 1n << 120n],
['avm_setOpcodeSmallField', 200n],
['avm_setOpcodeSmallField', 0x001234567890abcdef1234567890abcdefn],
['avm_setOpcodeBigField', 0x991234567890abcdef1234567890abcdefn],
])('Should execute contract SET functions', (name: string, res: bigint) => {
it(`Should execute contract function '${name}'`, async () => {
const context = initContext();
Expand Down
Loading