Files

50 lines
1.0 KiB
CMake
Raw Permalink Normal View History

function(add_example name)
set(target_name ${name}_example)
add_executable(${target_name} ${name}.c)
target_include_directories(${target_name} PRIVATE
${PROJECT_SOURCE_DIR}/include
)
target_link_libraries(${target_name}
secp256k1
$<$<PLATFORM_ID:Windows>:bcrypt>
)
add_test(NAME secp256k1.example.${name} COMMAND ${target_name})
2026-01-13 17:26:47 +00:00
set_tests_properties(secp256k1.example.${name} PROPERTIES
LABELS secp256k1_example
)
endfunction()
add_example(ecdsa)
if(SECP256K1_ENABLE_MODULE_ECDH)
add_example(ecdh)
endif()
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
add_example(schnorr)
endif()
if(SECP256K1_ENABLE_MODULE_ELLSWIFT)
add_example(ellswift)
endif()
if(SECP256K1_ENABLE_MODULE_MUSIG)
add_example(musig)
endif()
2026-08-31 00:05:16 +02:00
if(SECP256K1_ENABLE_MODULE_FROST)
add_example(frost)
endif()
chilldkg: Phase 6 - test vectors, FROST integration, docs, example Final phase of the ChillDKG module: upstream test vectors, a DKG->FROST integration test, boundary tests, full module documentation and a runnable example. Test vectors: - tools/test_vectors_chilldkg_generate.py converts all 10 upstream bip-frost-dkg JSON vector files into src/modules/chilldkg/vectors.h (modeled on tools/test_vectors_frost_generate.py; takes the vectors directory as an argument; upstream pinned to commit a91896883f85b159415ecf298d5e844879af112d, recorded in the generated header with the exact regeneration invocation; regeneration is reproducible byte-for-byte). - tests_impl.h vector runners execute 191 of 241 upstream cases through the public API: hostpubkey_gen, params_hash, participant_step1/step2/finalize/investigate, coordinator_step1/finalize/investigate, recover. Happy paths are byte-exact (pmsg1/cmsg1/pmsg2/cmsg2/dkg_output/recovery/cinv); error cases assert both the fault enum and fault_index against expectedError.participantId. The 50 skipped cases are wrong-length/wrong-count inputs not expressible with the fixed-size C API; each skip is documented in vectors.h. Boundary/robustness tests: t=1, t=n, n=2, a full n=128/t=2 session end-to-end with per-participant secshare*G == pubshare checks and a recovery roundtrip, and a state1 memcpy roundtrip (step2 from a copied state object). DKG->FROST integration test (guarded by ENABLE_MODULE_FROST): a full ChillDKG session (n=3, t=2) feeds (secshare, thresh_pk, pubshares) directly into the frost module. ChillDKG's thresh_pk is already TapTweak'ed, so frost_tweak_cache_init is called with no further tweaks (frost's tweaked x-only key asserted equal to the x-only part of the ChillDKG thresh_pk); signers 0 and 2 run nonce_gen, nonce_agg, session_init with the shared x = id+1 convention, frost_sign, partial_sig_verify and partial_sig_agg; the aggregate signature verifies as a plain BIP-340 signature against the threshold key. Example: examples/chilldkg.c runs a full 2-of-3 DKG session (host key generation, params hash, participant/coordinator steps, finalize, and a recovery roundtrip via participant_recover) with fixed-size buffers and secret erasure. Wired into Makefile.am and examples/CMakeLists.txt exactly like frost_example (runs as a TEST); chilldkg_example binary added to .gitignore. Docs: src/modules/chilldkg/chilldkg.md now documents the protocol summary, message-flow table with exact byte sizes, blame taxonomy, recovery workflow, security notes (host key reuse/retention, fresh randomness per session, state secrecy, recovery-data sensitivity) and the pinned reference commit; src/modules/frost/frost.md points at the new module as the intended DKG. Bug fix found by the vector runner (recover tcId 9): the internal recover() passed a possibly-NULL fault_index from coordinator_recover to certeq_verify, which dereferences it on failure; now uses a local. Verified: make check 10/10 (3 test suites + 7 examples incl. chilldkg_example, exit 0 when run); CMake ctest 428/428 with chilldkg + frost, and a no-frost build confirms the ENABLE_MODULE_FROST guard; make distdir includes vectors.h, the example and the generator. The module is feature-complete against bip-frost-dkg v0.3.0-dev at a91896883f85b159415ecf298d5e844879af112d. The BIP is still a draft; tagged hashes and wire formats may change upstream.
2026-08-31 06:52:58 +02:00
if(SECP256K1_ENABLE_MODULE_CHILLDKG)
add_example(chilldkg)
endif()
if(SECP256K1_ENABLE_MODULE_ICEBERG)
add_example(iceberg)
endif()
frost_enrollment: add the example program Fifth of six commits. examples/frost_enrollment.c runs a 2-of-3 group through an enrollment to 2-of-4, signs with the new participant, and then repairs a lost share -- all roles in one process, following examples/frost.c's structure. The example exists mostly to demonstrate two things the API cannot enforce and that a reader would otherwise have to reconstruct from the documentation. First, the verification flow, in the order that makes it non-circular: 1. obtain thresh_pk from a source authenticated INDEPENDENTLY of the helpers (here, the dealer step, commented as the stand-in); 2. validate the helpers' public shares against it with secp256k1_frost_threshold_info_validate; 3. derive the expected public share from those validated shares; 4. only then run round 2, passing the same authenticated thresh_pk. Skip step 1 or 2 and every check in round 2 still passes -- on a share from whatever polynomial t colluding helpers chose to present. The example says so at the point where it would be tempting to skip them. Second, the authorization gap. There is no authorization step in the protocol: anyone who convinces t helpers to run it receives a valid share, and in repair mode that is an existing participant's actual share. The precondition sits in the comment on enroll(), where a reader copying the function will see it, and again at the repair call site, which is where it bites hardest. Beyond that the example is a working reference for the parts that are fiddly to get right from the header alone: the transposition between round 1.1's output buffers and round 1.2's input buffer (helper j collects entry j of every helper's buffer), the opposite own-slot conventions of the two round-1.2 buffers, the n -> n+1 bookkeeping with threshold_info_validate over the extended table, and the fact that the resulting signature verifies against the group's ORIGINAL threshold public key, since enrollment changes neither the polynomial nor any existing share. The repair half asserts byte equality with the original secret share and the original public share, so a regression there fails the example rather than passing quietly. Wired into both build systems next to the iceberg example: Makefile.am (noinst_PROGRAMS and TESTS under ENABLE_MODULE_FROST_ENROLLMENT) and examples/CMakeLists.txt. The .gitignore entry landed with the Phase 1 scaffolding. Verification. Autotools: builds warning-free and `make check` reports 12/12 PASS including frost_enrollment_example; five consecutive runs exit 0 (the key material is freshly random each time, so this exercises both threshold-key parities in practice). CMake: with -DSECP256K1_BUILD_EXAMPLES=ON, ctest runs all nine examples and secp256k1.example.frost_enrollment passes; the full ctest suite is 523/523 with frost, chilldkg, iceberg, prefractal and frost-enrollment all enabled. The source is clean under gcc -std=c89 -pedantic -Wall -Wextra. Note for anyone reproducing this: examples are OFF by default in both build systems (--enable-examples for autotools, -DSECP256K1_BUILD_EXAMPLES=ON for CMake), so a plain build will not compile this file at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 04:30:48 +02:00
if(SECP256K1_ENABLE_MODULE_FROST_ENROLLMENT)
add_example(frost_enrollment)
endif()