Skip to content

feat!: add support for u1 in the avm circuit & witgen#8570

Merged
dbanks12 merged 1 commit into
masterfrom
db/u1-avm-circuit
Sep 18, 2024
Merged

feat!: add support for u1 in the avm circuit & witgen#8570
dbanks12 merged 1 commit into
masterfrom
db/u1-avm-circuit

Conversation

@dbanks12

@dbanks12 dbanks12 commented Sep 16, 2024

Copy link
Copy Markdown
Contributor
  • Circuit & witgen updates for u1
  • Simulator & transpiler updates for u1
  • Includes modification to the ToRadix AVM opcode to include the output_bits flag (is output in bits mode).
  • Includes modification to the ToRadix AVM and Brillig opcode's radix operand to be a memory offset instead of an immediate.
  • AVM comparator instructions (EQ/LT/LTE) now output U1.

radix_offset's read is not constrained due to #8603

dbanks12 commented Sep 16, 2024

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

Join @dbanks12 and the rest of your teammates on Graphite Graphite

@dbanks12 dbanks12 force-pushed the db/u1-avm-circuit branch 2 times, most recently from 876c708 to 34a7a3a Compare September 16, 2024 17:31
@dbanks12 dbanks12 marked this pull request as ready for review September 16, 2024 17:52
@dbanks12 dbanks12 removed the request for review from Maddiaa0 September 16, 2024 17:52
Comment thread yarn-project/simulator/src/avm/avm_memory_types.ts Outdated
Comment thread barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp
@dbanks12 dbanks12 marked this pull request as draft September 16, 2024 20:49
@dbanks12 dbanks12 force-pushed the db/u1-avm-circuit branch 2 times, most recently from cbdd5f0 to e2ddcf1 Compare September 17, 2024 17:28
Comment on lines 60 to 70
let num_bits = val.num_bits();
if num_bits < 8 {
if num_bits <= 8 {
8
} else if num_bits < 16 {
} else if num_bits <= 16 {
16
} else if num_bits < 32 {
} else if num_bits <= 32 {
32
} else if num_bits < 64 {
} else if num_bits <= 64 {
64
} else if num_bits < 128 {
} else if num_bits <= 128 {
128

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was just a bug

Comment on lines 70 to 74
{
std::string bytecode_hex = to_hex(OpCode::ADD_16) + // opcode ADD
"00" // Indirect flag
"01" // U8
std::string bytecode_hex = to_hex(OpCode::ADD_16) + // opcode ADD
"00" // Indirect flag
+ to_hex(AvmMemoryTag::U8) +
"0007" // addr a 7

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this across the whole file so that we aren't using magic numbers

Comment on lines +24 to +36
template <typename T>
requires(std::unsigned_integral<T>)
std::string to_hex(T value)
{
std::ostringstream stream;
auto num_bytes = static_cast<uint64_t>(sizeof(T));
auto mask = static_cast<uint64_t>((static_cast<uint128_t>(1) << (num_bytes * 8)) - 1);
auto padding = static_cast<int>(num_bytes * 2);
stream << std::setfill('0') << std::setw(padding) << std::hex << (value & mask);
return stream.str();
}

std::string to_hex(bb::avm_trace::AvmMemoryTag tag);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved from opcode.hpp because it's now useful for memory tags too

@dbanks12 dbanks12 force-pushed the db/u1-avm-circuit branch 2 times, most recently from 54870c3 to 6d7d35f Compare September 17, 2024 17:44
Comment on lines +102 to +109
type IntegralClass = typeof Uint1 | typeof Uint8 | typeof Uint16 | typeof Uint32 | typeof Uint64 | typeof Uint128;

describe.each([Uint1])('Integral Types (U1 only)', (clsValue: IntegralClass) => {
describe(`${clsValue.name}`, () => {
it(`Should construct a new ${clsValue.name} from a number`, () => {
const x = new clsValue(1);
expect(x.toBigInt()).toStrictEqual(1n);
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure it's worth spending the effort at this time to combine this with the test cases for non-U1 types since they use values other than 0 and 1.

Comment on lines 139 to 144
public toBuffer(): Buffer {
if (bits < 8) {
return toBufferBE(this.n, 1);
}
return toBufferBE(this.n, bits / 8);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need a whole byte for a Uint1

@dbanks12 dbanks12 marked this pull request as ready for review September 17, 2024 18:27
uint32_t dst_offset,
uint32_t radix_offset,
uint32_t num_limbs,
uint8_t output_bits)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this isn't of type bool?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just would be a one-off I think. Wasn't sure if I should leave it as a byte which is what it is in the wire format for the instruction. Instruction wire format operates in bytes.

But I could certainly change this to be type bool

Comment thread barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp
@TomAFrench

Copy link
Copy Markdown
Member

Hey all, this shouldn't cause a problem for noir syncing.

Using an older version of bb with the new brillig format will result in it misinterpreting the memory address as an immediate value but as bb doesn't use the brillig for anything, it won't cause any unexpected behaviour.

@jeanmon jeanmon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Very good job! Check my comments.

Comment thread barretenberg/cpp/pil/avm/alu.pil Outdated
// This holds the product over the integers
pol PRODUCT = a_lo * b_lo + LIMB_BITS_POW * partial_prod_lo + MAX_BITS_POW * (partial_prod_hi + a_hi * b_hi);
// (u1 multiplication only cares about a_lo and b_lo)
pol PRODUCT = a_lo * b_lo + (1 - u1_tag) * (LIMB_BITS_POW * partial_prod_lo + MAX_BITS_POW * (partial_prod_hi + a_hi * b_hi));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not need the exception for u1, ie., the term (1 - u1_tag) can be removed I think.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without that exception for u1, I believe a_hi and b_hi are underconstrained since LIMB_BITS_POW is 0. Or am I wrong?

Comment thread barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp Outdated
@dbanks12 dbanks12 force-pushed the db/u1-avm-circuit branch 2 times, most recently from 5066620 to e4c8a5b Compare September 18, 2024 15:22
@dbanks12 dbanks12 enabled auto-merge (squash) September 18, 2024 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants