What changed, and why it matters
This commit only adds a new automated fuzz test for Monero's Bulletproof+ range proof verification code. It does not change any production code, cryptographic logic, or network behavior. There is no indication this commit fixes or introduces a security issue.
No security action required. Treat as routine test infrastructure. If reviewing for security, ensure the underlying rct::bulletproof_plus_VERIFY() implementation is robust, but that is outside the scope of this commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff adds a bulletproof-plus fuzz target (tests/fuzz/bulletproof-plus.cpp), five binary seed corpus files, CMake build rules, and a shell script entry. The fuzzer deserializes a commitment vector and a BulletproofPlus proof, assigns the commitments to proof.V, and calls rct::bulletproof_plus_VERIFY(). No library or consensus code is modified.
Changed components
tests/fuzz/bulletproof-plus.cpptests/fuzz/CMakeLists.txtcontrib/fuzz_testing/fuzz.shtests/data/fuzz/bulletproof-plus/BP0-BP4Inspect captured patch +80 / −3
diff --git a/contrib/fuzz_testing/fuzz.sh b/contrib/fuzz_testing/fuzz.sh
index 065dcc3..45904c6 100755
--- a/contrib/fuzz_testing/fuzz.sh
+++ b/contrib/fuzz_testing/fuzz.sh
@@ -10,12 +10,12 @@ fi
type="$1"
if test -z "$type"
then
- echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|utf8|clsag|clsag_cout|clsag_message|clsag_pubs"
+ echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|bulletproof-plus|utf8|clsag|clsag_cout|clsag_message|clsag_pubs"
exit 1
fi
case "$type" in
- block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|utf8|clsag|clsag_cout|clsag_message|clsag_pubs) ;;
- *) echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|utf8|clsag|clsag_cout|clsag_message|clsag_pubs"; exit 1 ;;
+ block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|bulletproof-plus|utf8|clsag|clsag_cout|clsag_message|clsag_pubs) ;;
+ *) echo "usage: $0 block|transaction|signature|cold-outputs|cold-transaction|load-from-binary|load-from-json|base58|parse-url|http-client|levin|bulletproof|bulletproof-plus|utf8|clsag|clsag_cout|clsag_message|clsag_pubs"; exit 1 ;;
esac
if test -d "fuzz-out/$type"
diff --git a/tests/data/fuzz/bulletproof-plus/BP0 b/tests/data/fuzz/bulletproof-plus/BP0
new file mode 100644
index 0000000..a82eda8
Binary files /dev/null and b/tests/data/fuzz/bulletproof-plus/BP0 differ
diff --git a/tests/data/fuzz/bulletproof-plus/BP1 b/tests/data/fuzz/bulletproof-plus/BP1
new file mode 100644
index 0000000..0abf7b8
Binary files /dev/null and b/tests/data/fuzz/bulletproof-plus/BP1 differ
diff --git a/tests/data/fuzz/bulletproof-plus/BP2 b/tests/data/fuzz/bulletproof-plus/BP2
new file mode 100644
index 0000000..a76f66f
Binary files /dev/null and b/tests/data/fuzz/bulletproof-plus/BP2 differ
diff --git a/tests/data/fuzz/bulletproof-plus/BP3 b/tests/data/fuzz/bulletproof-plus/BP3
new file mode 100644
index 0000000..b24511c
Binary files /dev/null and b/tests/data/fuzz/bulletproof-plus/BP3 differ
diff --git a/tests/data/fuzz/bulletproof-plus/BP4 b/tests/data/fuzz/bulletproof-plus/BP4
new file mode 100644
index 0000000..050857d
Binary files /dev/null and b/tests/data/fuzz/bulletproof-plus/BP4 differ
diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
index 5d14c51..6db431e 100644
--- a/tests/fuzz/CMakeLists.txt
+++ b/tests/fuzz/CMakeLists.txt
@@ -268,6 +268,18 @@ set_property(TARGET bulletproof_fuzz_tests
PROPERTY
FOLDER "tests")
+monero_add_minimal_executable(bulletproof-plus_fuzz_tests bulletproof-plus.cpp fuzzer.cpp)
+target_link_libraries(bulletproof-plus_fuzz_tests
+ PRIVATE
+ ringct
+ serialization
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${EXTRA_LIBRARIES}
+ $ENV{LIB_FUZZING_ENGINE})
+set_property(TARGET bulletproof-plus_fuzz_tests
+ PROPERTY
+ FOLDER "tests")
+
monero_add_minimal_executable(tx-extra_fuzz_tests tx-extra.cpp fuzzer.cpp)
target_link_libraries(tx-extra_fuzz_tests
PRIVATE
diff --git a/tests/fuzz/bulletproof-plus.cpp b/tests/fuzz/bulletproof-plus.cpp
new file mode 100644
index 0000000..1a8c7bf
--- /dev/null
+++ b/tests/fuzz/bulletproof-plus.cpp
@@ -0,0 +1,65 @@
+// Copyright (c) 2026, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "include_base_utils.h"
+#include "fuzzer.h"
+#include "ringct/bulletproofs_plus.h"
+#include "serialization/binary_utils.h"
+
+#include <string>
+#include <utility>
+
+namespace
+{
+ struct fuzz_input
+ {
+ rct::keyV commitments;
+ rct::BulletproofPlus proof;
+
+ BEGIN_SERIALIZE_OBJECT()
+ FIELD(commitments)
+ FIELD(proof)
+ END_SERIALIZE()
+ };
+}
+
+BEGIN_INIT_SIMPLE_FUZZER()
+END_INIT_SIMPLE_FUZZER()
+
+BEGIN_SIMPLE_FUZZER()
+ if (len > 4096)
+ return 0;
+
+ fuzz_input input;
+ const std::string blob{reinterpret_cast<const char*>(buf), len};
+ if (!serialization::parse_binary(blob, input))
+ return 0;
+
+ input.proof.V = std::move(input.commitments);
+ rct::bulletproof_plus_VERIFY(input.proof);
+END_SIMPLE_FUZZER()
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.