-
Notifications
You must be signed in to change notification settings - Fork 270
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: add poseidon2 hashing to native transcript #3718
Changes from all commits
29a0d28
61c9eca
a8204fb
05085c5
99bd01d
029350c
a045b6d
86065bc
d50ac92
5f46e2d
d157087
f769528
e8702c7
86eae85
4a04326
2d16e5d
2c6406d
c0c715c
dd3366c
b37bed8
09f7ea2
7346629
1484030
97c2f88
e2f7526
f67148d
c0b5fb6
d3e110b
330c0c8
7fd7553
bbfb92b
a53a144
e12cb61
fe43adf
b1d5678
cab1312
54bb864
9cc55d1
87078b3
850ec4d
9f6293c
777e8b1
de5b619
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
#include "crypto/keccak/keccak.hpp" | ||
#include "crypto/pedersen_commitment/pedersen.hpp" | ||
#include "crypto/pedersen_hash/pedersen.hpp" | ||
#include "crypto/poseidon2/poseidon2.hpp" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added in an attempt to solve linker error, but probably still needed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seems like this file is unused so adding this is just for documentation about what is in barretenberg |
||
#include "crypto/schnorr/schnorr.hpp" | ||
#include "crypto/sha256/sha256.hpp" | ||
#include "ecc/curves/bn254/fq.hpp" | ||
|
@@ -41,6 +42,7 @@ | |
#include "stdlib/hash/blake2s/blake2s.hpp" | ||
#include "stdlib/hash/blake3s/blake3s.hpp" | ||
#include "stdlib/hash/pedersen/pedersen.hpp" | ||
#include "stdlib/hash/poseidon2/poseidon2.hpp" | ||
#include "stdlib/merkle_tree/hash.hpp" | ||
#include "stdlib/merkle_tree/membership.hpp" | ||
#include "stdlib/merkle_tree/memory_store.hpp" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,8 +59,8 @@ WASM_EXPORT void acir_create_proof(in_ptr acir_composer_ptr, | |
acir_composer->create_circuit(constraint_system, witness); | ||
|
||
acir_composer->init_proving_key(); | ||
auto proof_data = acir_composer->create_proof(*is_recursive); | ||
*out = to_heap_buffer(proof_data); | ||
auto proof = acir_composer->create_proof(*is_recursive); | ||
*out = to_heap_buffer(proof); | ||
} | ||
|
||
WASM_EXPORT void acir_goblin_accumulate(in_ptr acir_composer_ptr, | ||
|
@@ -73,8 +73,11 @@ WASM_EXPORT void acir_goblin_accumulate(in_ptr acir_composer_ptr, | |
auto witness = acir_format::witness_buf_to_witness_data(from_buffer<std::vector<uint8_t>>(witness_vec)); | ||
|
||
acir_composer->create_circuit(constraint_system, witness); | ||
auto proof_data = acir_composer->accumulate(); | ||
*out = to_heap_buffer(proof_data); | ||
auto proof = acir_composer->accumulate(); | ||
auto proof_data_buf = to_buffer</*include_size=*/true>( | ||
proof); // template parameter needs to be set so that vector deserialization from | ||
// buffer, which reads the size at the beginning can be done properly | ||
*out = to_heap_buffer(proof_data_buf); | ||
} | ||
|
||
WASM_EXPORT void acir_goblin_prove(in_ptr acir_composer_ptr, | ||
|
@@ -87,8 +90,11 @@ WASM_EXPORT void acir_goblin_prove(in_ptr acir_composer_ptr, | |
auto witness = acir_format::witness_buf_to_witness_data(from_buffer<std::vector<uint8_t>>(witness_vec)); | ||
|
||
acir_composer->create_circuit(constraint_system, witness); | ||
auto proof_data = acir_composer->accumulate_and_prove(); | ||
*out = to_heap_buffer(proof_data); | ||
auto proof = acir_composer->accumulate_and_prove(); | ||
auto proof_data_buf = to_buffer</*include_size=*/true>( | ||
proof); // template parameter needs to be set so that vector deserialization from | ||
// buffer, which reads the size at the beginning can be done properly | ||
*out = to_heap_buffer(proof_data_buf); | ||
} | ||
|
||
WASM_EXPORT void acir_load_verification_key(in_ptr acir_composer_ptr, uint8_t const* vk_buf) | ||
|
@@ -125,14 +131,16 @@ WASM_EXPORT void acir_get_proving_key(in_ptr acir_composer_ptr, uint8_t const* a | |
WASM_EXPORT void acir_goblin_verify_accumulator(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result) | ||
{ | ||
auto acir_composer = reinterpret_cast<acir_proofs::GoblinAcirComposer*>(*acir_composer_ptr); | ||
auto proof = from_buffer<std::vector<uint8_t>>(proof_buf); | ||
auto proof_data_buf = from_buffer<std::vector<uint8_t>>(proof_buf); | ||
auto proof = from_buffer<std::vector<bb::fr>>(proof_data_buf); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. flagging: should these transformations just become part of the methods the data is input to? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. clarify what that means? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. never mind - this was a note to self as I was going through. Nothing to do here |
||
*result = acir_composer->verify_accumulator(proof); | ||
} | ||
|
||
WASM_EXPORT void acir_goblin_verify(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result) | ||
{ | ||
auto acir_composer = reinterpret_cast<acir_proofs::GoblinAcirComposer*>(*acir_composer_ptr); | ||
auto proof = from_buffer<std::vector<uint8_t>>(proof_buf); | ||
auto proof_data_buf = from_buffer<std::vector<uint8_t>>(proof_buf); | ||
auto proof = from_buffer<std::vector<bb::fr>>(proof_data_buf); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So here and elsewhere we're taking a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can't skip an intermediate step because to_heap_buffer does not call to_buffer on the first call. If I can change that part of to_heap_buffer without breaking other things, then it might be fine, but just went with this to be safe. |
||
*result = acir_composer->verify(proof); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
|
||
#include "barretenberg/ecc/fields/field_conversion.hpp" | ||
|
||
namespace bb::field_conversion { | ||
|
||
static constexpr uint64_t NUM_CONVERSION_LIMB_BITS = 68; // set to be 68 because bigfield has 68 bit limbs | ||
static constexpr uint64_t TOTAL_BITS = 254; | ||
|
||
bb::fr convert_from_bn254_frs(std::span<const bb::fr> fr_vec, bb::fr* /*unused*/) | ||
{ | ||
ASSERT(fr_vec.size() == 1); | ||
return fr_vec[0]; | ||
} | ||
|
||
bool convert_from_bn254_frs(std::span<const bb::fr> fr_vec, bool* /*unused*/) | ||
{ | ||
ASSERT(fr_vec.size() == 1); | ||
return fr_vec[0] != 0; | ||
} | ||
|
||
/** | ||
* @brief Converts 2 bb::fr elements to grumpkin::fr | ||
* @details First, this function must take in 2 bb::fr elements because the grumpkin::fr field has a larger modulus than | ||
* the bb::fr field, so we choose to send 1 grumpkin::fr element to 2 bb::fr elements to maintain injectivity. | ||
* For the implementation, we want to minimize the number of constraints created by the circuit form, which happens to | ||
* use 68 bit limbs to represent a grumpkin::fr (as a bigfield). Therefore, our mapping will split a grumpkin::fr into a | ||
* 136 bit chunk for the lower two bigfield limbs and the upper chunk for the upper two limbs. The upper chunk ends up | ||
* being 254 - 2*68 = 118 bits as a result. This is why we check that the bb::frs must be at most 136 and 118 bits | ||
* respectively (to ensure no overflow). Then, we converts the two chunks to a grumpkin::fr using uint256_t conversions. | ||
* @param low_bits_in | ||
* @param high_bits_in | ||
* @return grumpkin::fr | ||
*/ | ||
grumpkin::fr convert_from_bn254_frs(std::span<const bb::fr> fr_vec, grumpkin::fr* /*unused*/) | ||
{ | ||
// Combines the two elements into one uint256_t, and then convert that to a grumpkin::fr | ||
ASSERT(uint256_t(fr_vec[0]) < (uint256_t(1) << (NUM_CONVERSION_LIMB_BITS * 2))); // lower 136 bits | ||
ASSERT(uint256_t(fr_vec[1]) < | ||
(uint256_t(1) << (TOTAL_BITS - NUM_CONVERSION_LIMB_BITS * 2))); // upper 254-136=118 bits | ||
uint256_t value = uint256_t(fr_vec[0]) + (uint256_t(fr_vec[1]) << (NUM_CONVERSION_LIMB_BITS * 2)); | ||
grumpkin::fr result(value); | ||
return result; | ||
} | ||
|
||
curve::BN254::AffineElement convert_from_bn254_frs(std::span<const bb::fr> fr_vec, | ||
curve::BN254::AffineElement* /*unused*/) | ||
{ | ||
curve::BN254::AffineElement val; | ||
val.x = convert_from_bn254_frs<grumpkin::fr>(fr_vec.subspan(0, 2)); | ||
val.y = convert_from_bn254_frs<grumpkin::fr>(fr_vec.subspan(2, 2)); | ||
return val; | ||
} | ||
|
||
curve::Grumpkin::AffineElement convert_from_bn254_frs(std::span<const bb::fr> fr_vec, | ||
curve::Grumpkin::AffineElement* /*unused*/) | ||
{ | ||
ASSERT(fr_vec.size() == 2); | ||
curve::Grumpkin::AffineElement val; | ||
val.x = fr_vec[0]; | ||
val.y = fr_vec[1]; | ||
return val; | ||
} | ||
|
||
/** | ||
* @brief Converts grumpkin::fr to 2 bb::fr elements | ||
* @details First, this function must return 2 bb::fr elements because the grumpkin::fr field has a larger modulus than | ||
* the bb::fr field, so we choose to send 1 grumpkin::fr element to 2 bb::fr elements to maintain injectivity. | ||
* This function the reverse of convert_from_bn254_frs(std::span<const bb::fr> fr_vec, grumpkin::fr*) by merging the two | ||
* pairs of limbs back into the 2 bb::fr elements. For the implementation, we want to minimize the number of constraints | ||
* created by the circuit form, which happens to use 68 bit limbs to represent a grumpkin::fr (as a bigfield). | ||
* Therefore, our mapping will split a grumpkin::fr into a 136 bit chunk for the lower two bigfield limbs and the upper | ||
* chunk for the upper two limbs. The upper chunk ends up being 254 - 2*68 = 118 bits as a result. We manipulate the | ||
* value using bitwise masks and shifts to obtain our two chunks. | ||
* @param input | ||
* @return std::array<bb::fr, 2> | ||
*/ | ||
std::vector<bb::fr> convert_to_bn254_frs(const grumpkin::fr& val) | ||
{ | ||
// Goal is to slice up the 64 bit limbs of grumpkin::fr/uint256_t to mirror the 68 bit limbs of bigfield | ||
// We accomplish this by dividing the grumpkin::fr's value into two 68*2=136 bit pieces. | ||
constexpr uint64_t LOWER_BITS = 2 * NUM_CONVERSION_LIMB_BITS; | ||
constexpr uint256_t LOWER_MASK = (uint256_t(1) << LOWER_BITS) - 1; | ||
auto value = uint256_t(val); | ||
ASSERT(value < (uint256_t(1) << TOTAL_BITS)); | ||
std::vector<bb::fr> result(2); | ||
result[0] = static_cast<uint256_t>(value & LOWER_MASK); | ||
result[1] = static_cast<uint256_t>(value >> LOWER_BITS); | ||
ASSERT(static_cast<uint256_t>(result[1]) < (uint256_t(1) << (TOTAL_BITS - LOWER_BITS))); | ||
return result; | ||
} | ||
|
||
std::vector<bb::fr> convert_to_bn254_frs(const bb::fr& val) | ||
{ | ||
std::vector<bb::fr> fr_vec{ val }; | ||
return fr_vec; | ||
} | ||
|
||
std::vector<bb::fr> convert_to_bn254_frs(const curve::BN254::AffineElement& val) | ||
{ | ||
auto fr_vec_x = convert_to_bn254_frs(val.x); | ||
auto fr_vec_y = convert_to_bn254_frs(val.y); | ||
std::vector<bb::fr> fr_vec(fr_vec_x.begin(), fr_vec_x.end()); | ||
fr_vec.insert(fr_vec.end(), fr_vec_y.begin(), fr_vec_y.end()); | ||
return fr_vec; | ||
} | ||
|
||
std::vector<bb::fr> convert_to_bn254_frs(const curve::Grumpkin::AffineElement& val) | ||
{ | ||
auto fr_vec_x = convert_to_bn254_frs(val.x); | ||
auto fr_vec_y = convert_to_bn254_frs(val.y); | ||
std::vector<bb::fr> fr_vec(fr_vec_x.begin(), fr_vec_x.end()); | ||
fr_vec.insert(fr_vec.end(), fr_vec_y.begin(), fr_vec_y.end()); | ||
return fr_vec; | ||
} | ||
|
||
} // namespace bb::field_conversion |
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.
not sure what this is doing but this helped me resolve some annoying linker errors, presumably introduced because goblin was introduced to main
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.
this is necessary from building without it/with it since transcript uses it, which is used by main.cpp in goblin_verify