Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,24 @@
#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
#include "barretenberg/polynomials/univariate.hpp"
#include "barretenberg/stdlib/primitives/bigfield/constants.hpp" // NUM_LIMB_BITS_IN_FIELD_SIMULATION
#include <limits>

namespace bb {

template <typename T, typename Value> T deserialize_bounded_integer(const Value& value)
{
if constexpr (std::is_same_v<T, uint32_t>) {
BB_ASSERT_LTE(uint256_t(value),
uint256_t(std::numeric_limits<uint32_t>::max()),
"Non-canonical uint32_t encoding: value exceeds uint32_t range");
} else if constexpr (std::is_same_v<T, uint64_t>) {
BB_ASSERT_LTE(uint256_t(value),
uint256_t(std::numeric_limits<uint64_t>::max()),
"Non-canonical uint64_t encoding: value exceeds uint64_t range");
}
return static_cast<T>(value);
}

class FrCodec {
public:
using DataType = bb::fr;
Expand Down Expand Up @@ -114,7 +129,9 @@ class FrCodec {
BB_ASSERT_EQ(fr_vec.size(), calc_num_fields<T>());
if constexpr (IsAnyOf<T, bool>) {
return static_cast<bool>(fr_vec[0]);
} else if constexpr (IsAnyOf<T, uint32_t, uint64_t, bb::fr>) {
} else if constexpr (IsAnyOf<T, uint32_t, uint64_t>) {
return deserialize_bounded_integer<T>(fr_vec[0]);
} else if constexpr (IsAnyOf<T, bb::fr>) {
return static_cast<T>(fr_vec[0]);
} else if constexpr (IsAnyOf<T, fq>) {
return convert_grumpkin_fr_from_bn254_frs(fr_vec);
Expand Down Expand Up @@ -277,7 +294,9 @@ class U256Codec {
} else if constexpr (IsAnyOf<T, fq>) {
BB_ASSERT_LT(vec[0], uint256_t(fq::modulus), "Non-canonical base field element: value >= fq::modulus");
return static_cast<T>(vec[0]);
} else if constexpr (IsAnyOf<T, uint32_t, uint64_t, uint256_t>) {
} else if constexpr (IsAnyOf<T, uint32_t, uint64_t>) {
return deserialize_bounded_integer<T>(vec[0]);
} else if constexpr (IsAnyOf<T, uint256_t>) {
return static_cast<T>(vec[0]);
} else if constexpr (IsAnyOf<T, bn254_commitment, grumpkin_commitment>) {
using BaseField = typename T::Fq;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "barretenberg/common/assert.hpp"
#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
#include <gtest/gtest.h>
#include <limits>

namespace bb::field_conversion_tests {

Expand All @@ -26,6 +27,43 @@ TEST_F(FieldConversionTest, FieldConversionUint32)
check_conversion(x);
}

TEST_F(FieldConversionTest, FrCodecRejectsOversizedUint32Metadata)
{
const std::vector<bb::fr> fields = { bb::fr((uint256_t(1) << 32) + 7) };
EXPECT_THROW_WITH_MESSAGE(FrCodec::deserialize_from_fields<uint32_t>(fields), "uint32_t");
}

TEST_F(FieldConversionTest, FrCodecRejectsOversizedUint64Metadata)
{
const std::vector<bb::fr> fields = { bb::fr((uint256_t(1) << 64) + 7) };
EXPECT_THROW_WITH_MESSAGE(FrCodec::deserialize_from_fields<uint64_t>(fields), "uint64_t");
}

TEST_F(FieldConversionTest, U256CodecRejectsOversizedUint32Metadata)
{
const std::vector<uint256_t> fields = { (uint256_t(1) << 32) + 7 };
EXPECT_THROW_WITH_MESSAGE(U256Codec::deserialize_from_fields<uint32_t>(fields), "uint32_t");
}

TEST_F(FieldConversionTest, U256CodecRejectsOversizedUint64Metadata)
{
const std::vector<uint256_t> fields = { (uint256_t(1) << 64) + 7 };
EXPECT_THROW_WITH_MESSAGE(U256Codec::deserialize_from_fields<uint64_t>(fields), "uint64_t");
}

TEST_F(FieldConversionTest, IntegerMetadataMaxValuesAccepted)
{
const auto max_u32 = std::numeric_limits<uint32_t>::max();
const auto max_u64 = std::numeric_limits<uint64_t>::max();

EXPECT_EQ(FrCodec::deserialize_from_fields<uint32_t>(std::vector<bb::fr>{ bb::fr(max_u32) }), max_u32);
EXPECT_EQ(FrCodec::deserialize_from_fields<uint64_t>(
std::vector<bb::fr>{ bb::fr(uint256_t(std::numeric_limits<uint64_t>::max())) }),
max_u64);
EXPECT_EQ(U256Codec::deserialize_from_fields<uint32_t>(std::vector<uint256_t>{ uint256_t(max_u32) }), max_u32);
EXPECT_EQ(U256Codec::deserialize_from_fields<uint64_t>(std::vector<uint256_t>{ uint256_t(max_u64) }), max_u64);
}

/**
* @brief Field conversion test for bb::fr
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "barretenberg/common/assert.hpp"
#include "barretenberg/flavor/mega_flavor.hpp"
#include "barretenberg/flavor/ultra_keccak_flavor.hpp"
#include "barretenberg/srs/global_crs.hpp"
Expand All @@ -7,6 +8,7 @@
#include "barretenberg/ultra_honk/prover_instance.hpp"

#include <gtest/gtest.h>
#include <type_traits>

using namespace bb;

Expand Down Expand Up @@ -106,3 +108,20 @@ TYPED_TEST(NativeVerificationKeyTests, FromFieldElementsRejectsWrongSize)
VerificationKey bad;
EXPECT_ANY_THROW(bad.from_field_elements(oversize));
}

TYPED_TEST(NativeVerificationKeyTests, FromFieldElementsRejectsOversizedMetadata)
{
using Flavor = typename TypeParam::Flavor;
using VerificationKey = typename Flavor::VerificationKey;
using DataType = typename VerificationKey::DataType;

std::vector<DataType> fields(VerificationKey::calc_num_data_types());
if constexpr (std::is_same_v<DataType, bb::fr>) {
fields[0] = bb::fr((uint256_t(1) << 64) + 1);
} else {
fields[0] = (uint256_t(1) << 64) + 1;
}

VerificationKey bad;
EXPECT_THROW_WITH_MESSAGE(bad.from_field_elements(fields), "uint64_t");
}
Loading