diff --git a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt index 14399cc02b2..e93015bdc77 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt @@ -6,6 +6,7 @@ barretenberg_module( stdlib_blake2s stdlib_keccak stdlib_pedersen_hash + stdlib_poseidon2 crypto_merkle_tree stdlib_schnorr crypto_sha256 diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 79f39889e56..47ca2e460a3 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -1,6 +1,5 @@ #include "acir_format.hpp" #include "barretenberg/common/log.hpp" -#include "barretenberg/dsl/acir_format/bigint_constraint.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" #include @@ -81,6 +80,9 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo create_pedersen_hash_constraint(builder, constraint); } + for (const auto& constraint : constraint_system.poseidon2_constraints) { + create_poseidon2_permutations(builder, constraint); + } // Add fixed base scalar mul constraints for (const auto& constraint : constraint_system.fixed_base_scalar_mul_constraints) { create_fixed_base_constraint(builder, constraint); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index c74607e7412..9a03f96d37a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -12,6 +12,7 @@ #include "keccak_constraint.hpp" #include "logic_constraint.hpp" #include "pedersen.hpp" +#include "poseidon2_constraint.hpp" #include "range_constraint.hpp" #include "recursion_constraint.hpp" #include "schnorr_verify.hpp" @@ -45,6 +46,7 @@ struct AcirFormat { std::vector keccak_permutations; std::vector pedersen_constraints; std::vector pedersen_hash_constraints; + std::vector poseidon2_constraints; std::vector fixed_base_scalar_mul_constraints; std::vector ec_add_constraints; std::vector recursion_constraints; @@ -77,6 +79,7 @@ struct AcirFormat { keccak_permutations, pedersen_constraints, pedersen_hash_constraints, + poseidon2_constraints, fixed_base_scalar_mul_constraints, ec_add_constraints, recursion_constraints, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp index 7107c95970a..481ceb5ee34 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp @@ -45,6 +45,7 @@ TEST_F(AcirFormatTests, TestASingleConstraintNoPubInputs) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -160,6 +161,7 @@ TEST_F(AcirFormatTests, TestLogicGateFromNoirCircuit) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -227,6 +229,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifyPass) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -322,6 +325,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifySmallRange) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -436,6 +440,7 @@ TEST_F(AcirFormatTests, TestVarKeccak) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -482,6 +487,7 @@ TEST_F(AcirFormatTests, TestKeccakPermutation) .keccak_permutations = { keccak_permutation }, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp index 44cfc8a1091..f7a5cbcf44d 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp @@ -10,6 +10,7 @@ #include "barretenberg/dsl/acir_format/keccak_constraint.hpp" #include "barretenberg/dsl/acir_format/logic_constraint.hpp" #include "barretenberg/dsl/acir_format/pedersen.hpp" +#include "barretenberg/dsl/acir_format/poseidon2_constraint.hpp" #include "barretenberg/dsl/acir_format/range_constraint.hpp" #include "barretenberg/dsl/acir_format/recursion_constraint.hpp" #include "barretenberg/dsl/acir_format/schnorr_verify.hpp" @@ -307,6 +308,12 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .result = arg.output, .opcode = BigIntOperationType::Div, }); + } else if constexpr (std::is_same_v) { + af.poseidon2_constraints.push_back(Poseidon2Constraint{ + .state = map(arg.inputs, [](auto& e) { return e.witness.value; }), + .result = map(arg.outputs, [](auto& e) { return e.value; }), + .len = arg.len, + }); } }, arg.value.value); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp index ab1035b0112..8527d395110 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp @@ -183,6 +183,7 @@ TEST_F(BigIntTests, TestBigIntConstraintMultiple) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -250,6 +251,7 @@ TEST_F(BigIntTests, TestBigIntConstraintSimple) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -302,6 +304,7 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -358,6 +361,7 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse2) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp index 37a4dd6dd53..3054120b4ba 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp @@ -126,6 +126,7 @@ TEST_F(UltraPlonkRAM, TestBlockConstraint) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp index 92dc537bfbd..559adcb6340 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp @@ -65,6 +65,7 @@ TEST_F(EcOperations, TestECOperations) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = { ec_add_constraint }, .recursion_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp index 9e546398c07..9ffffbabdd1 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp @@ -105,6 +105,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintSucceed) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -153,6 +154,7 @@ TEST_F(ECDSASecp256k1, TestECDSACompilesForVerifier) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -196,6 +198,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintFail) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp index 8269593eefb..99c28fdf33b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp @@ -140,6 +140,7 @@ TEST(ECDSASecp256r1, test_hardcoded) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -189,6 +190,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintSucceed) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -236,6 +238,7 @@ TEST(ECDSASecp256r1, TestECDSACompilesForVerifier) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -278,6 +281,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintFail) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.cpp index 0ca89314c69..205021739fa 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.cpp @@ -84,7 +84,6 @@ template void create_keccak_permutations(Builder& builder, co // Get the witness assignment for each witness index // Write the witness assignment to the byte_array for (size_t i = 0; i < constraint.state.size(); ++i) { - info(constraint.state[i]); state[i] = field_ct::from_witness_index(&builder, constraint.state[i]); } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.cpp new file mode 100644 index 00000000000..5380b48becc --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.cpp @@ -0,0 +1,41 @@ +#include "poseidon2_constraint.hpp" +#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp" + +namespace acir_format { +template void create_poseidon2_permutations(Builder& builder, const Poseidon2Constraint& constraint) +{ + using field_ct = bb::stdlib::field_t; + using Poseidon2Params = bb::stdlib::crypto::Poseidon2Bn254ScalarFieldParams; + using State = std::array; + + ASSERT(constraint.state.size() == constraint.len); + ASSERT(constraint.result.size() == constraint.len); + // Get the witness assignment for each witness index + // Write the witness assignment to the byte_array state + State state; + for (size_t i = 0; i < constraint.state.size(); ++i) { + state[i] = field_ct::from_witness_index(&builder, constraint.state[i]); + } + State output_state; + output_state = bb::stdlib::Poseidon2Permutation::permutation(&builder, state); + for (size_t i = 0; i < output_state.size(); ++i) { + poly_triple assert_equal{ + .a = output_state[i].normalize().witness_index, + .b = constraint.result[i], + .c = 0, + .q_m = 0, + .q_l = 1, + .q_r = -1, + .q_o = 0, + .q_c = 0, + }; + builder.create_poly_gate(assert_equal); + } +} + +template void create_poseidon2_permutations(UltraCircuitBuilder& builder, + const Poseidon2Constraint& constraint); + +template void create_poseidon2_permutations(GoblinUltraCircuitBuilder& builder, + const Poseidon2Constraint& constraint); +} // namespace acir_format \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.hpp new file mode 100644 index 00000000000..8ce677b016c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.hpp @@ -0,0 +1,21 @@ +#pragma once +#include "barretenberg/dsl/types.hpp" +#include "barretenberg/serialize/msgpack.hpp" +#include +#include + +namespace acir_format { + +struct Poseidon2Constraint { + std::vector state; + std::vector result; + uint32_t len; + + // For serialization, update with any new fields + MSGPACK_FIELDS(state, result, len); + friend bool operator==(Poseidon2Constraint const& lhs, Poseidon2Constraint const& rhs) = default; +}; + +template void create_poseidon2_permutations(Builder& builder, const Poseidon2Constraint& constraint); + +} // namespace acir_format \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.test.cpp new file mode 100644 index 00000000000..a7b02619734 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.test.cpp @@ -0,0 +1,82 @@ +#include "poseidon2_constraint.hpp" +#include "acir_format.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" + +#include +#include +#include + +namespace acir_format::tests { + +class Poseidon2Tests : public ::testing::Test { + protected: + static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } +}; +using fr = field; + +/** + * @brief Create a circuit testing the Poseidon2 permutation function + * + */ +TEST_F(Poseidon2Tests, TestPoseidon2Permutation) +{ + Poseidon2Constraint + poseidon2_constraint{ + .state = { 1, 2, 3, 4, }, + .result = { 5, 6, 7, 8, }, + .len = 4, + }; + + AcirFormat constraint_system{ .varnum = 9, + .recursive = false, + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .sha256_constraints = {}, + .sha256_compression = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .poseidon2_constraints = { poseidon2_constraint }, + .fixed_base_scalar_mul_constraints = {}, + .ec_add_constraints = {}, + .recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, + .bigint_operations = {}, + .constraints = {}, + .block_constraints = {} }; + + WitnessVector witness{ + 1, + 0, + 1, + 2, + 3, + bb::fr(std::string("0x01bd538c2ee014ed5141b29e9ae240bf8db3fe5b9a38629a9647cf8d76c01737")), + bb::fr(std::string("0x239b62e7db98aa3a2a8f6a0d2fa1709e7a35959aa6c7034814d9daa90cbac662")), + bb::fr(std::string("0x04cbb44c61d928ed06808456bf758cbf0c18d1e15a7b6dbc8245fa7515d5e3cb")), + bb::fr(std::string("0x2e11c5cff2a22c64d01304b778d78f6998eff1ab73163a35603f54794c30847a")), + }; + + auto builder = create_circuit(constraint_system, /*size_hint=*/0, witness); + + auto composer = Composer(); + auto prover = composer.create_ultra_with_keccak_prover(builder); + auto proof = prover.construct_proof(); + + auto verifier = composer.create_ultra_with_keccak_verifier(builder); + + EXPECT_EQ(verifier.verify_proof(proof), true); +} + +} // namespace acir_format::tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index 1c530678e87..bc1febd7409 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -98,6 +98,7 @@ Builder create_inner_circuit() .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, @@ -254,6 +255,7 @@ Builder create_outer_circuit(std::vector& inner_circuits) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = recursion_constraints, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp index fbce9f6e246..037473e31d4 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp @@ -48,6 +48,7 @@ TEST_F(Sha256Tests, TestSha256Compression) .keccak_permutations = {}, .pedersen_constraints = {}, .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, .fixed_base_scalar_mul_constraints = {}, .ec_add_constraints = {}, .recursion_constraints = {}, diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.cpp index 7ada288cc26..005050bc6dc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.cpp @@ -2,11 +2,12 @@ #include "barretenberg/proof_system/arithmetization/gate_data.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" +#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp" namespace bb::stdlib { /** - * @brief Circuit form of Poseidon2 permutation from https://eprint.iacr.org/2023/323. + * @brief Circuit form of Poseidon2 permutation from https://eprint.iacr.org/2023/323 for GoblinUltraCircuitBuilder. * @details The permutation consists of one initial linear layer, then a set of external rounds, a set of internal * rounds, and a set of external rounds. * @param builder @@ -16,6 +17,7 @@ namespace bb::stdlib { template typename Poseidon2Permutation::State Poseidon2Permutation::permutation( Builder* builder, const typename Poseidon2Permutation::State& input) + requires IsGoblinBuilder { // deep copy State current_state(input); @@ -26,7 +28,7 @@ typename Poseidon2Permutation::State Poseidon2Permutation::State Poseidon2Permutation +typename Poseidon2Permutation::State Poseidon2Permutation::permutation( + Builder* builder, const typename Poseidon2Permutation::State& input) + requires IsNotGoblinBuilder +{ + // deep copy + State current_state(input); + + // Apply 1st linear layer + matrix_multiplication_external(builder, current_state); + + // First set of external rounds + constexpr size_t rounds_f_beginning = rounds_f / 2; + for (size_t i = 0; i < rounds_f_beginning; ++i) { + add_round_constants(current_state, round_constants[i]); + apply_sbox(current_state); + matrix_multiplication_external(builder, current_state); + } + + // Internal rounds + const size_t p_end = rounds_f_beginning + rounds_p; + for (size_t i = rounds_f_beginning; i < p_end; ++i) { + current_state[0] += round_constants[i][0]; + apply_single_sbox(current_state[0]); + matrix_multiplication_internal(current_state); + } + + // Remaining external rounds + for (size_t i = p_end; i < NUM_ROUNDS; ++i) { + add_round_constants(current_state, round_constants[i]); + apply_sbox(current_state); + matrix_multiplication_external(builder, current_state); + } + return current_state; +} + +template +void Poseidon2Permutation::add_round_constants( + State& input, const typename Poseidon2Permutation::RoundConstants& rc) + requires IsNotGoblinBuilder + +{ + for (size_t i = 0; i < t; ++i) { + input[i] += rc[i]; + } +} + +template +void Poseidon2Permutation::apply_sbox(State& input) + requires IsNotGoblinBuilder +{ + for (auto& in : input) { + apply_single_sbox(in); + } +} + +template +void Poseidon2Permutation::apply_single_sbox(field_t& input) + requires IsNotGoblinBuilder +{ + // hardcoded assumption that d = 5. should fix this or not make d configurable + auto xx = input.sqr(); + auto xxxx = xx.sqr(); + input *= xxxx; +} + +template +void Poseidon2Permutation::matrix_multiplication_internal(State& input) + requires IsNotGoblinBuilder +{ + // for t = 4 + auto sum = input[0]; + for (size_t i = 1; i < t; ++i) { + sum += input[i]; + } + for (size_t i = 0; i < t; ++i) { + input[i] *= Params::internal_matrix_diagonal[i]; // internal_matrix_diagonal[i]; + input[i] += sum; + } +} + /** * @brief Separate function to do just the first linear layer (equivalent to external matrix mul). * @details We use 6 arithmetic gates to implement: @@ -105,7 +196,7 @@ typename Poseidon2Permutation::State Poseidon2Permutation -void Poseidon2Permutation::initial_external_matrix_multiplication( +void Poseidon2Permutation::matrix_multiplication_external( Builder* builder, typename Poseidon2Permutation::State& state) { // create the 6 gates for the initial matrix multiplication @@ -204,5 +295,6 @@ void Poseidon2Permutation::initial_external_matrix_multiplicati } template class Poseidon2Permutation; +template class Poseidon2Permutation; } // namespace bb::stdlib \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.hpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.hpp index 69a937533db..d653f8718c9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2_permutation.hpp @@ -4,6 +4,7 @@ #include #include "barretenberg/crypto/poseidon2/poseidon2_permutation.hpp" +#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp" #include "barretenberg/stdlib/primitives/field/field.hpp" namespace bb::stdlib { @@ -44,7 +45,19 @@ template class Poseidon2Permutation { * @param input * @return State */ - static State permutation(Builder* builder, const State& input); + static State permutation(Builder* builder, const State& input) + requires IsGoblinBuilder; + static State permutation(Builder* builder, const State& input) + requires IsNotGoblinBuilder; + + static void add_round_constants(State& input, const RoundConstants& rc) + requires IsNotGoblinBuilder; + static void apply_sbox(State& input) + requires IsNotGoblinBuilder; + static void apply_single_sbox(field_t& input) + requires IsNotGoblinBuilder; + static void matrix_multiplication_internal(State& input) + requires IsNotGoblinBuilder; /** * @brief Separate function to do just the first linear layer (equivalent to external matrix mul). @@ -59,9 +72,7 @@ template class Poseidon2Permutation { * @param builder * @param state */ - static void initial_external_matrix_multiplication(Builder* builder, State& state); + static void matrix_multiplication_external(Builder* builder, State& state); }; -extern template class Poseidon2Permutation; - } // namespace bb::stdlib \ No newline at end of file diff --git a/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/index.ts b/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/index.ts index f8c07e323b0..d5b573dc31c 100644 --- a/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/index.ts +++ b/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/index.ts @@ -32,7 +32,7 @@ export class BarretenbergWasmMain extends BarretenbergWasmBase { module: WebAssembly.Module, threads = Math.min(getNumCpu(), BarretenbergWasmMain.MAX_THREADS), logger: (msg: string) => void = debug, - initial = 26, + initial = 27, maximum = 2 ** 16, ) { this.logger = logger;