Skip to content

feat(avm): Port field gt to vm2#12883

Merged
sirasistant merged 11 commits intomasterfrom
arv/cmp_gadget_port
Mar 21, 2025
Merged

feat(avm): Port field gt to vm2#12883
sirasistant merged 11 commits intomasterfrom
arv/cmp_gadget_port

Conversation

@sirasistant
Copy link
Copy Markdown
Contributor

@sirasistant sirasistant commented Mar 19, 2025

Ports field greater than to vm2, removing non-ff and eq functionality, which could be trivally inlined in other gadgets.

@sirasistant sirasistant marked this pull request as ready for review March 19, 2025 17:34
sel * (128 - constant_128) = 0;

pol POW_128 = 2 ** 128;
pol P_LO = 53438638232309528389504892708671455233; // Lower 128 bits of p
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 p-1 in vm1, which was very counter intuitive

pol B_SUB_A_HI = b_hi - a_hi - borrow;

pol IS_GT = sel_gt * result;
// When IS_GT = 1, we enforce the condition that a > b and thus a - b - 1 does not underflow.
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.

Explainer comment taken from vm1

a_lo, constant_128
} in range_check.sel {
range_check.value, range_check.rng_chk_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.

nit: formatting should probably match what we typically do

// GT
TestParams{ 27, 0, true },
TestParams{ TWO_POW_128, 0, true },
TestParams{ FF::neg_one(), FF::zero(), true },
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.

FYI FF::zero() is being deprecated, #1270. We should probably get into the habit of not using them

Copy link
Copy Markdown
Contributor

@fcarreiro fcarreiro left a comment

Choose a reason for hiding this comment

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

Very sad about simulation :(. Will think a bit but IDK if there's a better way

bool operator==(const FFDecomposition& other) const = default;
};

struct LimbsComparisonWitness {
Copy link
Copy Markdown
Contributor

@fcarreiro fcarreiro Mar 20, 2025

Choose a reason for hiding this comment

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

Simulation should not have a concept of witness. I'd say find a proper rephrasing (also for the function) or we can discuss it.

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.

It's a witness in the general sense, it's a value used to prove a limb comparison. I know it's weird for simulation to have it, but right now simulation needs it to range check it ):

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.

This whole file feels very strange under simulation.

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.

Do you expect the functions to be used somewhere else or can they be put in field_gt?

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 think we can leave them under field gt yep. Do you think they should be simulator class static members? they are used in tests

Comment on lines +11 to +12
uint256_t a_integer = static_cast<uint256_t>(a);
uint256_t b_integer = static_cast<uint256_t>(b);
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.

Do you need the cast? If uint256_t has a constructor for FF it should be ok.

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.

ah let me see

@@ -0,0 +1,49 @@
#include "barretenberg/vm2/simulation/field_gt.hpp"
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.

"Include what you use"
in particular uint256_t, and the lib/field_comparison file.


namespace bb::avm2::simulation {

bool FieldGreaterThan::ff_gt(const FF& a, const FF& b)
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.

This whole method feels so so bad from a simulation PoV... but since we have to call the range check gadget I'm not sure there's a far better way...

Comment on lines +15 to +19
auto a_limbs = event.a_limbs;
auto p_sub_a_witness = event.p_sub_a_witness;
auto b_limbs = event.b_limbs;
auto p_sub_b_witness = event.p_sub_b_witness;
auto res_witness = event.res_witness;
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.

just fyi these are all making copies most likely. use auto& or better cost auto& if you want to avoid it.

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.

Also in general this use of auto is not very kosher. The rule of thumb is: "if the type can be known from context, you can use auto" but if it's not, ideally not, unless you do it for very specific reasons. E.g., you reaaaaaly don't need it, you want to avoid an include, type is too verbose, you need to destructure, etc.

Copy link
Copy Markdown
Contributor Author

@sirasistant sirasistant Mar 21, 2025

Choose a reason for hiding this comment

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

I do want the copy, because I'm going to mutate them to rotate them around (and the event comes as const&)
Regarding auto, will fix

@IlyasRidhuan
Copy link
Copy Markdown
Contributor

Very sad about simulation :(. Will think a bit but IDK if there's a better way

This seems to be a common issue we keep running into when it comes to inter-trace communication (we just accept it for "higher level" stuff like merkle -> poseidon2 or poseidon2 -> perm). This feels more egregious because it would otherwise be a 1-liner. Thinking out loud with some crazy ideas:

  1. We internalise the range check, this sucks because it will be ~16/17 extra columns to this trace. Although this trace should be pretty sparse and (hopefully) long term goblin work will make this not so bad.
  2. Allow some event generation within the various process functions in tracegen. So AvmTraceGenHelper would need to carry an emitter/s. The downside of this is that we lose some parallelisation - we essentially need to process the trace in the implicit hierarchy we have.

I dont mind (2) for range checks just because we will never directly call the range check - so we know that any range checks events is a result of another event.

@jeanmon
Copy link
Copy Markdown
Contributor

jeanmon commented Mar 21, 2025

  1. Allow some event generation within the various process functions in tracegen. So AvmTraceGenHelper would need to carry an emitter/s. The downside of this is that we lose some parallelisation - we essentially need to process the trace in the implicit hierarchy we have.

@IlyasRidhuan @fcarreiro I was thinking the same the other day when calling a range check from bytecode_manager.cpp felt artificial. I think that what we cannot reconcile is directly emitting per each subtrace in simulation and not leaking circuit stuff into simulation. This will happen for each inter-circuit calls which is meant to be internal. We can still maintain parallelism in the tracegen if we can trigger these "internal inter-subtrace events" at event generation. For instance, through some "kind of event listeners" mechanism (e.g., rangecheck emitter listens to instr_fetching_event and emits whenever this happens). I did not study the code though to see how this could be done concretely (observer pattern?). @fcarreiro is the master on this.

@IlyasRidhuan
Copy link
Copy Markdown
Contributor

hmm maybe, but i think that would just be moving the logic to the range check (thereby overloading it) when it should really just be in tracegen.

The problem is that some of the internal range check calls involve work that the simulation shouldnt care about. If you want to trigger them at event generation, you will still need to do the "internal computation" while we are simulating, which we want to avoid. E.g. in FF_GT we range check some value a_lo, IMO a_lo should only exist in tracegen time, it's not necessary for a pure simulator to know about a_lo. But even with the listener approach, we need to compute a_lo somewhere during simulation even though we might never use it.

@jeanmon
Copy link
Copy Markdown
Contributor

jeanmon commented Mar 21, 2025

@IlyasRidhuan Good point about values to be generated during simulation. We should be able to abstract the computation of such "circuit relevant values" based on the "parent event" and the "observer" could derive such values before emitting its own event. If you run the simulator with the "no-event" mode, then the work made by the observer is gone and you really simulate only what you need. What I am trying to do is move logic which needs to be done at simulation but for circuit only purposes into this "observer layer". This is done during simulation (in emit events mode) time but in a separate place.

Copy link
Copy Markdown
Contributor

Thank you for the ideas guys. I have to think about them (maybe after hints?) since all of them have ramifications that cannot be taken lightly. I think for now I'm ok with polluting the simulator like this, and at least keeping the properties we already know about. If I come up with something else and a new set of properties we can probably refactor the (hopefully few) gadgets that do things like this.

@sirasistant
Copy link
Copy Markdown
Contributor Author

It's funny because this took me longer since the first implementation I did it with a one liner in simulation. Then I went to constraining and i was like OH WAIT how will the range check gadget know about my range checks, and I had to go back and pollute simulation and the event with internal information.

Copy link
Copy Markdown
Contributor

@fcarreiro fcarreiro left a comment

Choose a reason for hiding this comment

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

LRTM (looks reasonable to me) :)

Will let Ilyas/@jeanmon approve the PIL

std::get<6>(evals) += typename Accumulator::View(tmp);
}
{
{ // INITIALIZE_CURRENT_NODE
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.

I thought these were already on master?

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.

Maybe they were generated with an old bb-pilcom? Will regen mine with latest build just in case

uint128_t res_witness_hi = a_hi - b_hi - 0;

EXPECT_THAT(range_checks,
ElementsAreArray({ a_lo,
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.

ElementsAreArray is useful when you already have an array variable. Otherwise ElementsAre(a,b,c,d...) should just work without needing to construct an array/vector.

Same in other places.

Comment on lines +80 to +86
assert(field_gt.ff_gt(1, 0));
assert(field_gt.ff_gt(-1, 0));

assert(!field_gt.ff_gt(0, 0));
assert(!field_gt.ff_gt(-1, -1));
assert(!field_gt.ff_gt(0, 1));
assert(!field_gt.ff_gt(0, -1));
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.

I think you might want these to be EXPECT_EQ()s?

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.

yup it'd be a bit better


namespace bb::avm2::simulation {

const uint256_t TWO_POW_128 = uint256_t{ 1 } << 128;
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.

nit: prefer uint256_t(1). Brace initialization is a can of worms. I like to follow this: https://abseil.io/tips/88

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.

Can also be a constexpr most likely.

(also check if it's not already in the constants gen)

@sirasistant sirasistant merged commit 0ae6891 into master Mar 21, 2025
7 checks passed
@sirasistant sirasistant deleted the arv/cmp_gadget_port branch March 21, 2025 17:36
PhilWindle pushed a commit that referenced this pull request Mar 24, 2025
🤖 I have created a new Aztec Packages release
---


##
[0.82.1](v0.82.0...v0.82.1)
(2025-03-24)


### Features

* **avm:** Port field gt to vm2
([#12883](#12883))
([0ae6891](0ae6891))
* use msgpack for ClientIvc::Proof in API
([#12911](#12911))
([1a01602](1a01602))


### Bug Fixes

* disable proving on vite box
([#12971](#12971))
([69a0fb6](69a0fb6))
* no hardcoded versions in bbup
([#12944](#12944))
([397144f](397144f))
* pull CRS data ahead of time
([#12945](#12945))
([43155d6](43155d6))
* Remove workaround
([#12952](#12952))
([c3337af](c3337af))
* set the correct env var
([#12959](#12959))
([bd0f4b2](bd0f4b2))
* yolo add bunch of test flakes
([13c19da](13c19da))
* yolo e2e_p2p tests now fully skipped due to huge speed regression
([9141410](9141410))
* yolo txe binds just to localhost by default.
([3933b35](3933b35))


### Miscellaneous

* Change `/bin/bash` shebang to be env based
([#12834](#12834))
([7843a67](7843a67))
* clean up avm codeowners
([#12860](#12860))
([35a8f46](35a8f46))
* deflake the kind smoke test
([#12955](#12955))
([1a37d6d](1a37d6d)),
closes
[#11177](#11177)
* fee cleanup
([#12941](#12941))
([fdf1da4](fdf1da4))
* Increase bot count
([#12963](#12963))
([16edd06](16edd06))
* L2 chain config for alpha testnet
([#12962](#12962))
([e13edb8](e13edb8))
* Reduce bots
([#12953](#12953))
([4bbc5da](4bbc5da))
* remove selector from public call request
([#12828](#12828))
([18bcc1b](18bcc1b))
* replace relative paths to noir-protocol-circuits
([61cf4b6](61cf4b6))
* replace relative paths to noir-protocol-circuits
([4356c17](4356c17))
* replace relative paths to noir-protocol-circuits
([f73f47d](f73f47d))
* Set default proving config to true
([#12964](#12964))
([75c1549](75c1549))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
DanielKotov pushed a commit that referenced this pull request Mar 27, 2025
Ports field greater than to vm2, removing non-ff and eq functionality,
which could be trivally inlined in other gadgets.
DanielKotov pushed a commit that referenced this pull request Mar 27, 2025
🤖 I have created a new Aztec Packages release
---


##
[0.82.1](v0.82.0...v0.82.1)
(2025-03-24)


### Features

* **avm:** Port field gt to vm2
([#12883](#12883))
([0ae6891](0ae6891))
* use msgpack for ClientIvc::Proof in API
([#12911](#12911))
([1a01602](1a01602))


### Bug Fixes

* disable proving on vite box
([#12971](#12971))
([69a0fb6](69a0fb6))
* no hardcoded versions in bbup
([#12944](#12944))
([397144f](397144f))
* pull CRS data ahead of time
([#12945](#12945))
([43155d6](43155d6))
* Remove workaround
([#12952](#12952))
([c3337af](c3337af))
* set the correct env var
([#12959](#12959))
([bd0f4b2](bd0f4b2))
* yolo add bunch of test flakes
([13c19da](13c19da))
* yolo e2e_p2p tests now fully skipped due to huge speed regression
([9141410](9141410))
* yolo txe binds just to localhost by default.
([3933b35](3933b35))


### Miscellaneous

* Change `/bin/bash` shebang to be env based
([#12834](#12834))
([7843a67](7843a67))
* clean up avm codeowners
([#12860](#12860))
([35a8f46](35a8f46))
* deflake the kind smoke test
([#12955](#12955))
([1a37d6d](1a37d6d)),
closes
[#11177](#11177)
* fee cleanup
([#12941](#12941))
([fdf1da4](fdf1da4))
* Increase bot count
([#12963](#12963))
([16edd06](16edd06))
* L2 chain config for alpha testnet
([#12962](#12962))
([e13edb8](e13edb8))
* Reduce bots
([#12953](#12953))
([4bbc5da](4bbc5da))
* remove selector from public call request
([#12828](#12828))
([18bcc1b](18bcc1b))
* replace relative paths to noir-protocol-circuits
([61cf4b6](61cf4b6))
* replace relative paths to noir-protocol-circuits
([4356c17](4356c17))
* replace relative paths to noir-protocol-circuits
([f73f47d](f73f47d))
* Set default proving config to true
([#12964](#12964))
([75c1549](75c1549))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
DanielKotov pushed a commit that referenced this pull request Mar 27, 2025
Ports field greater than to vm2, removing non-ff and eq functionality,
which could be trivally inlined in other gadgets.
DanielKotov pushed a commit that referenced this pull request Mar 27, 2025
🤖 I have created a new Aztec Packages release
---


##
[0.82.1](v0.82.0...v0.82.1)
(2025-03-24)


### Features

* **avm:** Port field gt to vm2
([#12883](#12883))
([0ae6891](0ae6891))
* use msgpack for ClientIvc::Proof in API
([#12911](#12911))
([1a01602](1a01602))


### Bug Fixes

* disable proving on vite box
([#12971](#12971))
([69a0fb6](69a0fb6))
* no hardcoded versions in bbup
([#12944](#12944))
([397144f](397144f))
* pull CRS data ahead of time
([#12945](#12945))
([43155d6](43155d6))
* Remove workaround
([#12952](#12952))
([c3337af](c3337af))
* set the correct env var
([#12959](#12959))
([bd0f4b2](bd0f4b2))
* yolo add bunch of test flakes
([13c19da](13c19da))
* yolo e2e_p2p tests now fully skipped due to huge speed regression
([9141410](9141410))
* yolo txe binds just to localhost by default.
([3933b35](3933b35))


### Miscellaneous

* Change `/bin/bash` shebang to be env based
([#12834](#12834))
([7843a67](7843a67))
* clean up avm codeowners
([#12860](#12860))
([35a8f46](35a8f46))
* deflake the kind smoke test
([#12955](#12955))
([1a37d6d](1a37d6d)),
closes
[#11177](#11177)
* fee cleanup
([#12941](#12941))
([fdf1da4](fdf1da4))
* Increase bot count
([#12963](#12963))
([16edd06](16edd06))
* L2 chain config for alpha testnet
([#12962](#12962))
([e13edb8](e13edb8))
* Reduce bots
([#12953](#12953))
([4bbc5da](4bbc5da))
* remove selector from public call request
([#12828](#12828))
([18bcc1b](18bcc1b))
* replace relative paths to noir-protocol-circuits
([61cf4b6](61cf4b6))
* replace relative paths to noir-protocol-circuits
([4356c17](4356c17))
* replace relative paths to noir-protocol-circuits
([f73f47d](f73f47d))
* Set default proving config to true
([#12964](#12964))
([75c1549](75c1549))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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.

4 participants