-
Notifications
You must be signed in to change notification settings - Fork 297
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: (bb) remove redundant constraints on field/group elements when using goblin plonk #8409
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
a99a244
oink alpha challenges are now generated simultaneously instead of one…
zac-williamson 5eaab18
split biggroup_goblin into a distinct class and renamed `biggroup` in…
zac-williamson a18be4f
compiler fixes, namespace changes
zac-williamson 7b5d591
comments, changes
zac-williamson 33f2e5a
fix rebase error
zac-williamson c757190
rebase fixes
zac-williamson bd708ab
comments, more rebase fixes
zac-williamson f8875a8
fixed goblin_field error where wrong constant was being used
zac-williamson 6de4b04
cleanup
zac-williamson 12aaebd
comment fix
zac-williamson b1806ec
Merge branch 'master' into zw/biggroup_goblin
zac-williamson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
114 changes: 114 additions & 0 deletions
114
barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/goblin_field.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#pragma once | ||
#include "../bigfield/bigfield.hpp" | ||
#include "../circuit_builders/circuit_builders_fwd.hpp" | ||
#include "../field/field.hpp" | ||
|
||
namespace bb::stdlib { | ||
|
||
/** | ||
* @brief goblin_field wraps x/y coordinates of bn254 group elements when using goblin | ||
* @details this class exists because we do not want to parametrise goblin bn254 coordinates with bigfield. | ||
* bigfield generates a large number of constraints to apply checks that are not needed for goblin coordinates | ||
* This is because, in the goblin context we can apply the following heuristics: | ||
* 1. goblin coordinate field elements are range-constrained in the Translator circuit (no need to range | ||
* constrain here) | ||
* 2. field elements that come out of the ECCVM are well-formed, we do not need to call `assert_is_in_field` | ||
* 3. there should be no need to apply arithmetic to goblin coordinate field elements in-circuit | ||
* Having a distinct class for `goblin_field` allows us to harvest these optimisations without a proliferation | ||
* of edge cases and bloated logic in other classes | ||
* @tparam Builder | ||
*/ | ||
template <class Builder> class goblin_field { | ||
public: | ||
static constexpr uint1024_t DEFAULT_MAXIMUM_REMAINDER = | ||
bigfield<Builder, bb::Bn254FqParams>::DEFAULT_MAXIMUM_REMAINDER; | ||
static constexpr size_t NUM_LIMBS = bigfield<Builder, bb::Bn254FqParams>::NUM_LIMBS; | ||
static constexpr size_t NUM_LIMB_BITS = bigfield<Builder, bb::Bn254FqParams>::NUM_LIMB_BITS; | ||
static constexpr size_t NUM_LAST_LIMB_BITS = bigfield<Builder, bb::Bn254FqParams>::NUM_LAST_LIMB_BITS; | ||
|
||
using field_ct = stdlib::field_t<Builder>; | ||
using bool_ct = stdlib::bool_t<Builder>; | ||
std::array<field_ct, 2> limbs; | ||
|
||
// constructors mirror bigfield constructors | ||
goblin_field() | ||
: limbs{ 0, 0 } | ||
{} | ||
goblin_field(Builder* parent_context, const uint256_t& value) | ||
{ | ||
(*this) = goblin_field(bb::fq(value)); | ||
limbs[0].context = parent_context; | ||
limbs[1].context = parent_context; | ||
} | ||
goblin_field(bb::fq input) | ||
{ | ||
uint256_t converted(input); | ||
uint256_t lo_v = converted.slice(0, NUM_LIMB_BITS * 2); | ||
uint256_t hi_v = converted.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3 + NUM_LAST_LIMB_BITS); | ||
limbs = { bb::fr(lo_v), bb::fr(hi_v) }; | ||
} | ||
goblin_field(field_ct lo, field_ct hi) | ||
: limbs{ lo, hi } | ||
{} | ||
|
||
// N.B. this method is because AggregationState expects group element coordinates to be split into 4 slices | ||
// (we could update to only use 2 for Mega but that feels complex) | ||
goblin_field(field_ct lolo, field_ct lohi, field_ct hilo, field_ct hihi, [[maybe_unused]] bool can_overflow = false) | ||
: limbs{ lolo + lohi * (uint256_t(1) << NUM_LIMB_BITS), hilo + hihi * (uint256_t(1) << NUM_LIMB_BITS) } | ||
{} | ||
|
||
void assert_equal(const goblin_field& other) const | ||
{ | ||
limbs[0].assert_equal(other.limbs[0]); | ||
limbs[1].assert_equal(other.limbs[1]); | ||
} | ||
static goblin_field zero() { return goblin_field{ 0, 0 }; } | ||
|
||
static goblin_field from_witness(Builder* ctx, bb::fq input) | ||
{ | ||
uint256_t converted(input); | ||
uint256_t lo_v = converted.slice(0, NUM_LIMB_BITS * 2); | ||
uint256_t hi_v = converted.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3 + NUM_LAST_LIMB_BITS); | ||
field_ct lo = field_ct::from_witness(ctx, lo_v); | ||
field_ct hi = field_ct::from_witness(ctx, hi_v); | ||
return goblin_field(lo, hi); | ||
} | ||
|
||
static goblin_field conditional_assign(const bool_ct& predicate, const goblin_field& lhs, goblin_field& rhs) | ||
{ | ||
goblin_field result; | ||
result.limbs = { | ||
field_ct::conditional_assign(predicate, lhs.limbs[0], rhs.limbs[0]), | ||
field_ct::conditional_assign(predicate, lhs.limbs[1], rhs.limbs[1]), | ||
}; | ||
return result; | ||
} | ||
|
||
// matches the interface for bigfield | ||
uint512_t get_value() const | ||
{ | ||
uint256_t lo = limbs[0].get_value(); | ||
uint256_t hi = limbs[1].get_value(); | ||
uint256_t result = lo + (hi << 136); | ||
return result; | ||
} | ||
|
||
// matches the interface for bigfield | ||
uint512_t get_maximum_value() const { return (*this).get_value(); } | ||
|
||
Builder* get_context() const | ||
{ | ||
if (limbs[0].get_context()) { | ||
return limbs[0].get_context(); | ||
} | ||
return limbs[1].get_context(); | ||
} | ||
|
||
// done in the translator circuit | ||
void assert_is_in_field(){}; | ||
}; | ||
template <typename C> inline std::ostream& operator<<(std::ostream& os, goblin_field<C> const& v) | ||
{ | ||
return os << "{ " << v.limbs[0] << " , " << v.limbs[1] << " }"; | ||
} | ||
} // namespace bb::stdlib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this is good cleanup.