UltrafastSecp256k1 3.50.0
Ultra high-performance secp256k1 elliptic curve cryptography library
Loading...
Searching...
No Matches
zk.hpp
Go to the documentation of this file.
1#ifndef SECP256K1_ZK_HPP
2#define SECP256K1_ZK_HPP
3#pragma once
4
5// ============================================================================
6// Zero-Knowledge Proof Layer for secp256k1
7// ============================================================================
8// Implements ZK proof primitives over the secp256k1 curve:
9//
10// 1. Schnorr Knowledge Proof (sigma protocol)
11// - Non-interactive proof of knowledge of discrete log
12// - Prove: "I know x such that P = x*G" without revealing x
13//
14// 2. DLEQ Proof (Discrete Log Equality)
15// - Prove: log_G(P) == log_H(Q) without revealing the secret
16// - Used in: VRFs, adaptor signatures, ECDH proofs, atomic swaps
17//
18// 3. Bulletproof Range Proof
19// - Prove: committed value v in [0, 2^n) without revealing v
20// - Logarithmic proof size via inner product argument
21// - Used in: Confidential Transactions, Mimblewimble, Liquid
22//
23// Security: All proving operations use CT layer (constant-time).
24// Verification uses fast layer (variable-time, public data).
25//
26// Fiat-Shamir: All proofs are non-interactive via tagged SHA-256 hashing.
27// ============================================================================
28
29#include <array>
30#include <cstdint>
31#include <cstddef>
32#include "secp256k1/scalar.hpp"
33#include "secp256k1/point.hpp"
35
36namespace secp256k1 {
37namespace zk {
38
39// ============================================================================
40// 1. Schnorr Knowledge Proof (Sigma Protocol)
41// ============================================================================
42// Non-interactive proof of knowledge of discrete log.
43// Proves: "I know x such that P = x*G" (or P = x*B for arbitrary base B).
44//
45// Protocol (Fiat-Shamir):
46// Prover: k <- random, R = k*G, e = H("ZK/knowledge" || R || P || msg), s = k + e*x
47// Verifier: s*G == R + e*P
48//
49// Proof size: 64 bytes (R_compressed[33] + s[32] -> optimized to R.x[32] + s[32])
50
52 std::array<std::uint8_t, 32> rx; // R.x (x-coordinate of nonce point)
53 fast::Scalar s; // response scalar
54
55 std::array<std::uint8_t, 64> serialize() const;
56 static bool deserialize(const std::uint8_t* data64, KnowledgeProof& out);
57};
58
59// Prove knowledge of secret x such that pubkey = x*G
60// msg: optional binding message (32 bytes, can be all-zero)
61// aux_rand: 32 bytes entropy for nonce hedging
63 const fast::Point& pubkey,
64 const std::array<std::uint8_t, 32>& msg,
65 const std::array<std::uint8_t, 32>& aux_rand);
66
67// Verify knowledge proof against public key and message
69 const fast::Point& pubkey,
70 const std::array<std::uint8_t, 32>& msg);
71
72// Prove knowledge of secret x such that point = x*base (arbitrary base)
74 const fast::Point& point,
75 const fast::Point& base,
76 const std::array<std::uint8_t, 32>& msg,
77 const std::array<std::uint8_t, 32>& aux_rand);
78
79// Verify knowledge proof against arbitrary base
81 const fast::Point& point,
82 const fast::Point& base,
83 const std::array<std::uint8_t, 32>& msg);
84
85
86// ============================================================================
87// 2. DLEQ Proof (Discrete Log Equality)
88// ============================================================================
89// Proves: log_G(P) == log_H(Q), i.e., P = x*G and Q = x*H for same x.
90//
91// Protocol (Fiat-Shamir):
92// Prover: k <- random, R1 = k*G, R2 = k*H
93// e = H("ZK/dleq" || G || H || P || Q || R1 || R2)
94// s = k + e*x
95// Verifier: s*G == R1 + e*P AND s*H == R2 + e*Q
96//
97// Used in VRFs, DLEQ-based adaptor signatures, provable ECDH.
98// Proof size: 64 bytes (e[32] + s[32])
99
100struct DLEQProof {
101 fast::Scalar e; // challenge
102 fast::Scalar s; // response
103
104 std::array<std::uint8_t, 64> serialize() const;
105 static bool deserialize(const std::uint8_t* data64, DLEQProof& out);
106};
107
108// Prove that log_G(P) == log_H(Q) where P = secret*G and Q = secret*H
109// aux_rand: 32 bytes entropy for nonce hedging
111 const fast::Point& G,
112 const fast::Point& H,
113 const fast::Point& P,
114 const fast::Point& Q,
115 const std::array<std::uint8_t, 32>& aux_rand);
116
117// Verify DLEQ proof
118bool dleq_verify(const DLEQProof& proof,
119 const fast::Point& G,
120 const fast::Point& H,
121 const fast::Point& P,
122 const fast::Point& Q);
123
124
125// ============================================================================
126// 3. Bulletproof Range Proof
127// ============================================================================
128// Proves that a Pedersen commitment C = v*H + r*G commits to v in [0, 2^n).
129// Based on Bulletproofs (Bunz et al., 2018).
130//
131// Proof structure:
132// - A, S: vector commitment points (2 group elements)
133// - T1, T2: polynomial commitment points (2 group elements)
134// - tau_x, mu, t_hat: scalar values (3 scalars)
135// - L[], R[]: inner product argument (2*log2(n) group elements)
136// - a, b: final inner product scalars (2 scalars)
137//
138// For n=64 bits: 2*log2(64) = 12 group elements + 7 scalars = ~620 bytes
139// Verification: O(n) multi-exp (can batch across multiple proofs)
140
141static constexpr std::size_t RANGE_PROOF_BITS = 64;
142static constexpr std::size_t RANGE_PROOF_LOG2 = 6; // log2(64)
143
145 // Vector commitments
146 fast::Point A; // commitment to bits vector
147 fast::Point S; // commitment to blinding vectors
148
149 // Polynomial commitments
150 fast::Point T1; // commitment to t_1 coefficient
151 fast::Point T2; // commitment to t_2 coefficient
152
153 // Scalar responses
154 fast::Scalar tau_x; // blinding for polynomial eval
155 fast::Scalar mu; // aggregate blinding
156 fast::Scalar t_hat; // polynomial evaluation at challenge
157
158 // Inner product argument (log2(n) rounds)
159 std::array<fast::Point, RANGE_PROOF_LOG2> L;
160 std::array<fast::Point, RANGE_PROOF_LOG2> R;
161
162 // Final scalars
165};
166
167// Generate range proof for a Pedersen commitment
168// value: the committed value (must be in [0, 2^64))
169// blinding: the blinding factor used in the commitment
170// commitment: the Pedersen commitment C = value*H + blinding*G
171// aux_rand: 32 bytes of entropy
172RangeProof range_prove(std::uint64_t value,
173 const fast::Scalar& blinding,
174 const PedersenCommitment& commitment,
175 const std::array<std::uint8_t, 32>& aux_rand);
176
177// Verify range proof for a Pedersen commitment
178// Returns true if the proof is valid (committed value is in [0, 2^64))
179bool range_verify(const PedersenCommitment& commitment,
180 const RangeProof& proof);
181
182
183// ============================================================================
184// Generator Vectors (for Bulletproofs)
185// ============================================================================
186// Nothing-up-my-sleeve generators: G_i = H("BP_G" || LE32(i)), H_i = H("BP_H" || LE32(i))
187// Cached after first computation.
188
190 std::array<fast::Point, RANGE_PROOF_BITS> G;
191 std::array<fast::Point, RANGE_PROOF_BITS> H;
192};
193
195
196
197// ============================================================================
198// Batch Operations
199// ============================================================================
200
201// Batch-verify multiple range proofs (more efficient than individual verification)
202// Returns true only if ALL proofs are valid.
204 const RangeProof* proofs,
205 std::size_t count);
206
207// Batch-create Pedersen commitments (performance optimization)
208// values[count], blindings[count] -> commitments_out[count]
209void batch_commit(const fast::Scalar* values,
210 const fast::Scalar* blindings,
211 PedersenCommitment* commitments_out,
212 std::size_t count);
213
214} // namespace zk
215} // namespace secp256k1
216
217#endif // SECP256K1_ZK_HPP
void batch_commit(const fast::Scalar *values, const fast::Scalar *blindings, PedersenCommitment *commitments_out, std::size_t count)
const GeneratorVectors & get_generator_vectors()
static constexpr std::size_t RANGE_PROOF_LOG2
Definition zk.hpp:142
RangeProof range_prove(std::uint64_t value, const fast::Scalar &blinding, const PedersenCommitment &commitment, const std::array< std::uint8_t, 32 > &aux_rand)
bool range_verify(const PedersenCommitment &commitment, const RangeProof &proof)
DLEQProof dleq_prove(const fast::Scalar &secret, const fast::Point &G, const fast::Point &H, const fast::Point &P, const fast::Point &Q, const std::array< std::uint8_t, 32 > &aux_rand)
bool batch_range_verify(const PedersenCommitment *commitments, const RangeProof *proofs, std::size_t count)
bool dleq_verify(const DLEQProof &proof, const fast::Point &G, const fast::Point &H, const fast::Point &P, const fast::Point &Q)
KnowledgeProof knowledge_prove(const fast::Scalar &secret, const fast::Point &pubkey, const std::array< std::uint8_t, 32 > &msg, const std::array< std::uint8_t, 32 > &aux_rand)
static constexpr std::size_t RANGE_PROOF_BITS
Definition zk.hpp:141
bool knowledge_verify_base(const KnowledgeProof &proof, const fast::Point &point, const fast::Point &base, const std::array< std::uint8_t, 32 > &msg)
KnowledgeProof knowledge_prove_base(const fast::Scalar &secret, const fast::Point &point, const fast::Point &base, const std::array< std::uint8_t, 32 > &msg, const std::array< std::uint8_t, 32 > &aux_rand)
bool knowledge_verify(const KnowledgeProof &proof, const fast::Point &pubkey, const std::array< std::uint8_t, 32 > &msg)
fast::Scalar s
Definition zk.hpp:102
fast::Scalar e
Definition zk.hpp:101
std::array< std::uint8_t, 64 > serialize() const
static bool deserialize(const std::uint8_t *data64, DLEQProof &out)
std::array< fast::Point, RANGE_PROOF_BITS > H
Definition zk.hpp:191
std::array< fast::Point, RANGE_PROOF_BITS > G
Definition zk.hpp:190
std::array< std::uint8_t, 64 > serialize() const
std::array< std::uint8_t, 32 > rx
Definition zk.hpp:52
static bool deserialize(const std::uint8_t *data64, KnowledgeProof &out)
fast::Scalar tau_x
Definition zk.hpp:154
std::array< fast::Point, RANGE_PROOF_LOG2 > R
Definition zk.hpp:160
fast::Scalar mu
Definition zk.hpp:155
fast::Scalar t_hat
Definition zk.hpp:156
std::array< fast::Point, RANGE_PROOF_LOG2 > L
Definition zk.hpp:159