Fix tests failing in release build#11
Conversation
|
Also, the PR title doesn't represent the change, since it's not Conan-related at all, but tests failing in Release builds. |
There was a problem hiding this comment.
Pull request overview
This PR aims to make the test suite reliable in Release builds (where assert() may be compiled out) and to centralize scalar/field backend selection in CMake to avoid macro redefinition warnings and mismatched build settings.
Changes:
- Replaced
assert()usage across tests with persistentEXPECT(...)-style macros that abort/exit on failure. - Moved scalar/field backend selection into top-level
CMakeLists.txtand removed backend#defineblocks fromsrc/mpt_scalar.c. - Updated/cleaned several tests (including allocation strategies and proof generation/verification flows), and removed the old
tests/test_bulletproof.c.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
CMakeLists.txt |
Adds global architecture/int128 detection and sets scalar/field backend compile definitions. |
src/mpt_scalar.c |
Removes manual backend #defines to rely on CMake-provided compile definitions. |
tests/test_same_plaintext_multi_shared_r.c |
Refactors shared-r equality test to use EXPECT, changes RNG seeding, and simplifies verification flow. |
tests/test_same_plaintext_multi.c |
Replaces assert with EXPECT, switches from VLAs to heap allocations for broader compiler compatibility. |
tests/test_same_plaintext.c |
Replaces assert with EXPECT and adds extra debugging helper (currently unused). |
tests/test_pok_sk.c |
Replaces assert with EXPECT and adds safer scalar generation helper. |
tests/test_link_proof.c |
Replaces assert with EXPECT and adds safer scalar generation helper. |
tests/test_ipa.c |
Replaces assert with EXPECT and hardens RNG checks. |
tests/test_equality_proof.c |
Replaces assert with EXPECT and consolidates test runner setup. |
tests/test_elgamal_verify.c |
Replaces assert with EXPECT; uses keypair-gen to obtain valid scalar for randomness. |
tests/test_elgamal.c |
Replaces assert with EXPECT and adds end-of-run success message. |
tests/test_commitments.c |
Replaces assert with EXPECT and hardens RNG failure handling. |
tests/test_bulletproof_agg.c |
Replaces assert with EXPECT and removes local prototypes in favor of header declarations. |
tests/test_bulletproof.c |
Removed. |
.gitignore |
Ignores IntelliJ and Python venv directories. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
CMakeLists.txt
Outdated
| if (HAVE_INT128_T OR CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm64" | ||
| OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") | ||
| message(STATUS "Build: Detected 64-bit system. Enforcing 64-bit arithmetic globally.") | ||
| add_compile_definitions(USE_SCALAR_4X64 USE_FIELD_5X52 HAVE___INT128) | ||
| else () | ||
| message(STATUS "Build: Detected 32-bit system. Enforcing generic arithmetic globally.") |
There was a problem hiding this comment.
The architecture detection enables USE_SCALAR_4X64 and defines HAVE___INT128 whenever the CPU looks 64-bit, even if CheckTypeSize("unsigned __int128") fails. On toolchains without unsigned __int128 (e.g., MSVC x64), this can force the 4x64 backend and HAVE___INT128, likely breaking compilation or producing incorrect scalar math. Suggest gating USE_SCALAR_4X64/HAVE___INT128 strictly on HAVE_INT128_T (and otherwise fall back to USE_SCALAR_8X32), or adding a separate, verified MSVC-compatible 64-bit path.
| if (HAVE_INT128_T OR CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm64" | |
| OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") | |
| message(STATUS "Build: Detected 64-bit system. Enforcing 64-bit arithmetic globally.") | |
| add_compile_definitions(USE_SCALAR_4X64 USE_FIELD_5X52 HAVE___INT128) | |
| else () | |
| message(STATUS "Build: Detected 32-bit system. Enforcing generic arithmetic globally.") | |
| if (HAVE_INT128_T) | |
| message(STATUS "Build: Detected compiler support for unsigned __int128. Enforcing 64-bit arithmetic backend.") | |
| add_compile_definitions(USE_SCALAR_4X64 USE_FIELD_5X52 HAVE___INT128) | |
| else () | |
| message(STATUS "Build: No unsigned __int128 support detected. Using generic 32-bit arithmetic backend.") |
There was a problem hiding this comment.
I've updated CMakeLists.txt to use the definitions that actually exist in the source.
| unsigned char seed[32]; | ||
| if (RAND_bytes(seed, 32) == 1) { | ||
| secp256k1_context_randomize(ctx, seed); | ||
| } | ||
| FILE *fr = fopen("/dev/urandom", "r"); | ||
| EXPECT(fr != NULL, "Failed to open /dev/urandom"); | ||
| EXPECT(fread(seed, 1, 32, fr) == 32, "Failed to read random seed"); | ||
| fclose(fr); |
There was a problem hiding this comment.
This test seeds randomness by reading from "/dev/urandom". That’s non-portable (fails on Windows and some restricted environments) and duplicates the project’s existing OpenSSL-based RNG usage elsewhere in the test suite. Prefer using RAND_bytes() (or a shared helper) for the seed/context bytes so tests remain cross-platform.
There was a problem hiding this comment.
Fixed. I removed the non-portable /dev/urandom code and replaced it with the random_bytes() helper (wrapping RAND_bytes) to ensure cross-platform compatibility.
| // 4. Verify Proof | ||
| res = secp256k1_mpt_verify_equality_shared_r( | ||
| ctx, proof, | ||
| N_RECIPIENTS, | ||
| &C1, C2_tampered, Pk, tx_id | ||
| &C1, | ||
| C2s, // Pass the array directly | ||
| pks, // Pass the array directly | ||
| tx_context | ||
| ); | ||
| assert(res == 0); | ||
| printf("Tamper detection: OK.\n"); | ||
|
|
||
| /* 8. Negative Test: Tamper with Transaction Context */ | ||
| printf("Verifying proof with wrong TxID (Expecting Failure)...\n"); | ||
| unsigned char tx_id_fake[32]; | ||
| memcpy(tx_id_fake, tx_id, 32); | ||
| tx_id_fake[0] ^= 0xFF; // Flip bits | ||
| EXPECT(res == 1, "Proof Verification Function returned failure"); | ||
| printf("Proof verified successfully.\n"); |
There was a problem hiding this comment.
The negative test coverage was removed: previously this test verified that tampering with ciphertexts and with the transaction context causes verification to fail. With only the positive-path verification remaining, regressions in binding / malleability checks may go undetected. Consider reintroducing at least one ciphertext-tamper case and one context-tamper case with EXPECT(res == 0).
There was a problem hiding this comment.
Fixed. I have reintroduced negative test cases.
| #include <openssl/rand.h> | ||
| #include <stdlib.h> // Added for malloc/free | ||
|
|
||
| #include <time.h> |
There was a problem hiding this comment.
#include <time.h> appears unused in this test after the refactor. If the project builds with warnings enabled, this can introduce noise; consider removing unused includes.
| #include <time.h> |
tests/test_same_plaintext.c
Outdated
| /* Helper to dump pubkey bytes for debugging */ | ||
| static void dump_pubkey_raw(const char* name, const secp256k1_pubkey* pk) { | ||
| const unsigned char* p = (const unsigned char*)pk; | ||
| printf("%s raw: ", name); | ||
| for (size_t i = 0; i < sizeof(*pk); i++) printf("%02x", p[i]); | ||
| printf("\n"); | ||
| } |
There was a problem hiding this comment.
dump_pubkey_raw is defined but not used. With common warning flags (e.g., -Wunused-function), this can fail CI if warnings are treated as errors. Consider removing it or wrapping it in a debug-only conditional (e.g., #ifdef DEBUG) and/or using it in an assertion failure path.
There was a problem hiding this comment.
Fixed. Removed the unused dump_pubkey_raw function.
| // 3. Generate Proof | ||
| unsigned char proof[1024]; | ||
|
|
||
| // UPDATED CALL: Removed 'proof_len' | ||
| res = secp256k1_mpt_verify_equality_shared_r( | ||
| // Passing flat arrays 'C2s' and 'pks' directly. | ||
| int res = secp256k1_mpt_prove_equality_shared_r( | ||
| ctx, proof, | ||
| amount, // correct arg order | ||
| r, | ||
| N_RECIPIENTS, | ||
| &C1, C2, Pk, tx_id | ||
| &C1, | ||
| C2s, // Pass the array directly | ||
| pks, // Pass the array directly | ||
| tx_context |
There was a problem hiding this comment.
The proof buffer is hard-coded to unsigned char proof[1024];. For N=3 this happens to be larger than secp256k1_mpt_proof_equality_shared_r_size(N_RECIPIENTS), but it no longer documents/validates the required size and could silently become wrong if the proof format or recipient count changes. Prefer sizing the buffer using secp256k1_mpt_proof_equality_shared_r_size(N_RECIPIENTS) (stack VLA or malloc) to match the API contract.
There was a problem hiding this comment.
Fixed. Updated proof buffers to use the _size() API helper instead of hard-coded values.
|
I simplified cmake further - we don't need to have a separate variable, if move the section further down |
|
Thanks, that looks great! Moving the logic down and using PRIVATE definitions is much cleaner. I appreciate the simplification! |
Tests: Replaced assert() in all test files with a custom persistent EXPECT() macro. This guarantees that cryptographic setup logic executes correctly in both Debug and Release modes.
CMake: Moved architecture detection into CMakeLists.txt using CheckTypeSize. It now automatically detects 128-bit support and applies the optimized 64-bit flags (USE_SCALAR_4X64) globally.
Cleanup: Removed manual #define blocks from src/mpt_scalar.c to rely entirely on CMake, preventing "macro redefinition" warnings.
Verification I have verified that all tests now pass successfully in both Debug and Release modes on macOS.