UltrafastSecp256k1/examples/basic_usage/main.cpp
vano c347bae204 feat: v2.2.0 — ECDSA (RFC 6979), Schnorr (BIP-340), SHA-256, CI/CD, fuzzing, CT bench
New features:
- ECDSA sign/verify with RFC 6979 deterministic nonce (HMAC-SHA256)
- Schnorr BIP-340 sign/verify with tagged hashing & x-only pubkeys
- Self-contained SHA-256 (header-only, no deps)
- Scalar::inverse (Fermat's theorem), negate(), is_even()

Build & tooling:
- GitHub Actions CI: Linux (gcc-13/clang-17), Windows (MSVC), macOS
- .clang-format + .editorconfig for code style
- cmake/version.hpp.in auto-generated version header
- CMake VERSION 1.0.0 -> 2.2.0
- Fixed install(TARGETS/EXPORT) — moved to cpu/ where target is defined
- MSVC compatibility via SECP256K1_NO_INT128 generator expression
- Fixed BUILD_TESTING standalone build

Testing & benchmarks:
- test_ecdsa_schnorr: 22 checks (SHA-256 NIST, inverse, ECDSA, Schnorr)
- bench_ct: CT vs fast comparison for all primitives
- 3 libFuzzer harnesses (field, scalar, point)
- Desktop CLI example (examples/basic_usage)

All 5 CTest targets pass (22/22 ECDSA+Schnorr checks).
2026-02-15 05:03:33 +04:00

96 lines
3.5 KiB
C++

// ============================================================================
// UltrafastSecp256k1 — Desktop Quick-Start Example
// ============================================================================
// Demonstrates basic usage: key generation, point operations, serialization.
// Build: cmake --build <build_dir> --target example_basic_usage
// ============================================================================
#include <chrono>
#include <cstdio>
#include <cstdint>
#include "secp256k1/field.hpp"
#include "secp256k1/scalar.hpp"
#include "secp256k1/point.hpp"
#include "secp256k1/selftest.hpp"
using namespace secp256k1::fast;
// ── helpers ──────────────────────────────────────────────────────────────────
static void print_hex(const char* label, const uint8_t* data, size_t len) {
printf(" %s: ", label);
for (size_t i = 0; i < len; ++i) printf("%02x", data[i]);
printf("\n");
}
static double now_us() {
using clk = std::chrono::high_resolution_clock;
static auto t0 = clk::now();
return std::chrono::duration<double, std::micro>(clk::now() - t0).count();
}
// ── main ─────────────────────────────────────────────────────────────────────
int main() {
printf("=== UltrafastSecp256k1 — Basic Usage Example ===\n\n");
// 1) Self-test
printf("[1] Running self-test...\n");
bool ok = Selftest(false);
printf(" Result: %s\n\n", ok ? "PASS" : "FAIL");
if (!ok) return 1;
// 2) Create a private key (scalar)
printf("[2] Key generation\n");
auto priv = Scalar::from_hex(
"e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35");
auto pub = Point::generator().scalar_mul(priv);
auto compressed = pub.to_compressed();
auto uncompressed = pub.to_uncompressed();
printf(" Private key : %s\n", priv.to_hex().c_str());
print_hex("Public (comp)", compressed.data(), compressed.size());
print_hex("Public (uncomp)", uncompressed.data(), uncompressed.size());
printf("\n");
// 3) Point arithmetic
printf("[3] Point arithmetic\n");
auto G = Point::generator();
auto G2 = G.dbl();
auto G3 = G2.add(G);
printf(" G x = %s\n", G.x().to_hex().c_str());
printf(" 2G x = %s\n", G2.x().to_hex().c_str());
printf(" 3G x = %s\n", G3.x().to_hex().c_str());
printf("\n");
// 4) Scalar arithmetic
printf("[4] Scalar arithmetic\n");
auto a = Scalar::from_uint64(7);
auto b = Scalar::from_uint64(13);
auto c = a * b;
printf(" 7 * 13 mod n = %s\n", c.to_hex().c_str());
printf(" Expected 91 = ...5b (last byte)\n\n");
// 5) Micro-benchmark: scalar_mul(k, G)
printf("[5] Benchmark: k * G (1000 iterations)\n");
constexpr int ITERS = 1000;
auto k = Scalar::from_hex(
"0000000000000000000000000000000000000000000000000000000000000001");
volatile uint8_t sink = 0;
double t0 = now_us();
for (int i = 0; i < ITERS; ++i) {
auto P = G.scalar_mul(k);
sink ^= P.to_compressed()[0];
k += Scalar::one();
}
double elapsed = now_us() - t0;
printf(" Total : %.1f ms\n", elapsed / 1000.0);
printf(" Per op: %.1f us\n", elapsed / ITERS);
printf(" (sink = 0x%02x)\n\n", (unsigned)sink);
printf("=== Done ===\n");
return 0;
}