diff --git a/barretenberg/cpp/src/barretenberg/api/api_ultra_honk.cpp b/barretenberg/cpp/src/barretenberg/api/api_ultra_honk.cpp index 0e51705b34ee..345b65b02fe1 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_ultra_honk.cpp +++ b/barretenberg/cpp/src/barretenberg/api/api_ultra_honk.cpp @@ -121,14 +121,14 @@ bool UltraHonkAPI::verify(const Flags& flags, if (auto json = try_parse_json(public_inputs_content)) { public_inputs = PublicInputsJson::parse(*json); } else { - public_inputs = many_from_buffer(public_inputs_content); + public_inputs = many_from_buffer_exact(public_inputs_content, "UltraHonk public inputs file"); } auto proof_content = read_file(proof_path); if (auto json = try_parse_json(proof_content)) { proof = ProofJson::parse(*json); } else { - proof = many_from_buffer(proof_content); + proof = many_from_buffer_exact(proof_content, "UltraHonk proof file"); } auto vk_content = read_file(vk_path); diff --git a/barretenberg/cpp/src/barretenberg/api/file_io.hpp b/barretenberg/cpp/src/barretenberg/api/file_io.hpp index 42cbaf6ab05f..894e7f537ffa 100644 --- a/barretenberg/cpp/src/barretenberg/api/file_io.hpp +++ b/barretenberg/cpp/src/barretenberg/api/file_io.hpp @@ -1,5 +1,6 @@ #pragma once #include "barretenberg/common/log.hpp" +#include "barretenberg/common/serialize.hpp" #include "barretenberg/common/try_catch_shim.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include @@ -9,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -153,6 +155,16 @@ inline std::vector read_vk_file(const std::filesystem::path& vk_path) } } +template +inline std::vector many_from_buffer_exact(const std::vector& buffer, std::string_view object_name) +{ + if (buffer.size() % sizeof(T) != 0) { + THROW std::runtime_error(std::string(object_name) + " size must be a multiple of " + std::to_string(sizeof(T)) + + " bytes, got " + std::to_string(buffer.size())); + } + return ::many_from_buffer(buffer); +} + // On Windows, std::filesystem::path uses wide strings (wchar_t) and doesn't implicitly convert // to std::string. On Linux/macOS (libstdc++), the conversion is implicit so these aren't needed. #ifdef _WIN32 diff --git a/barretenberg/cpp/src/barretenberg/api/file_io.test.cpp b/barretenberg/cpp/src/barretenberg/api/file_io.test.cpp new file mode 100644 index 000000000000..7769de2ea5b2 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/api/file_io.test.cpp @@ -0,0 +1,25 @@ +#include "barretenberg/api/file_io.hpp" +#include "barretenberg/common/assert.hpp" +#include "barretenberg/common/serialize.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include + +using namespace bb; + +TEST(APIFileIO, ManyFromBufferExactRejectsTrailingBytes) +{ + std::vector bytes(sizeof(uint256_t) + 1, 0); + + EXPECT_THROW_WITH_MESSAGE((many_from_buffer_exact(bytes, "UltraHonk proof file")), + "UltraHonk proof file size must be a multiple of 32 bytes, got 33"); +} + +TEST(APIFileIO, ManyFromBufferExactAcceptsAlignedBuffers) +{ + std::vector expected{ uint256_t(1), uint256_t(2) }; + auto bytes = to_buffer(expected); + + auto parsed = many_from_buffer_exact(bytes, "UltraHonk proof file"); + + EXPECT_EQ(parsed, expected); +}