purify
C++ Purify implementation with native circuit and BPP support
Loading...
Searching...
No Matches
bppp.hpp
Go to the documentation of this file.
1// Copyright (c) 2026 Judica, Inc.
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or https://opensource.org/license/mit/.
4
10#pragma once
11
12#include <array>
13#include <cstdint>
14#include <span>
15#include <utility>
16
17#include "purify/api.hpp"
18#include "purify/bppp.hpp"
19
21
22using Scalar32 = std::array<unsigned char, 32>;
23using XOnly32 = std::array<unsigned char, 32>;
24using Signature64 = std::array<unsigned char, 64>;
25
27struct TopicProofCache;
28struct Signature;
29class PreparedNonce;
30
31struct NonceProof;
32struct ProvenSignature;
33
34struct PublicKey {
35 static constexpr std::size_t kSerializedSize = 96;
36
39
44 [[nodiscard]] Bytes serialize() const;
45
51 [[nodiscard]] static Result<PublicKey> deserialize(std::span<const unsigned char> serialized,
52 purify_secp_context* secp_context);
53
59 [[nodiscard]] static Result<PublicKey> from_secret(const SecretKey& secret,
60 purify_secp_context* secp_context);
61
68 [[nodiscard]] Result<bool> verify_signature(std::span<const unsigned char> message,
69 const Signature& signature,
70 purify_secp_context* secp_context) const;
71
80 std::span<const unsigned char> message,
81 const NonceProof& nonce_proof,
82 purify_secp_context* secp_context,
83 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
84
93 const MessageProofCache& cache,
94 const NonceProof& nonce_proof,
95 purify_secp_context* secp_context,
96 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
97
106 std::span<const unsigned char> topic,
107 const NonceProof& nonce_proof,
108 purify_secp_context* secp_context,
109 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
110
119 const TopicProofCache& cache,
120 const NonceProof& nonce_proof,
121 purify_secp_context* secp_context,
122 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
123
132 std::span<const unsigned char> message,
133 const ProvenSignature& signature,
134 purify_secp_context* secp_context,
135 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
136
145 const MessageProofCache& cache,
146 const ProvenSignature& signature,
147 purify_secp_context* secp_context,
148 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
149
159 std::span<const unsigned char> message,
160 std::span<const unsigned char> topic,
161 const ProvenSignature& signature,
162 purify_secp_context* secp_context,
163 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
164
174 const TopicProofCache& cache,
175 std::span<const unsigned char> message,
176 const ProvenSignature& signature,
177 purify_secp_context* secp_context,
178 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
179};
180
182struct Nonce {
183 static constexpr std::size_t kSerializedSize = 32;
184
186
188 [[nodiscard]] Bytes serialize() const;
190 [[nodiscard]] static Result<Nonce> deserialize(std::span<const unsigned char> serialized,
191 purify_secp_context* secp_context);
192};
193
195struct Signature {
196 static constexpr std::size_t kSerializedSize = 64;
197
199
201 [[nodiscard]] Nonce nonce() const;
203 [[nodiscard]] Scalar32 s() const;
205 [[nodiscard]] Bytes serialize() const;
207 [[nodiscard]] static Result<Signature> deserialize(std::span<const unsigned char> serialized,
208 purify_secp_context* secp_context);
209};
210
232
254
256 static constexpr unsigned char kSerializationVersion = 1;
257
261
262 [[nodiscard]] Result<Bytes> serialize(purify_secp_context* secp_context) const;
263 [[nodiscard]] static Result<NonceProof> deserialize(std::span<const unsigned char> serialized,
264 purify_secp_context* secp_context);
265};
266
268 static constexpr unsigned char kSerializationVersion = 1;
269
272
273 [[nodiscard]] Result<Bytes> serialize(purify_secp_context* secp_context) const;
274 [[nodiscard]] static Result<ProvenSignature> deserialize(std::span<const unsigned char> serialized,
275 purify_secp_context* secp_context);
276};
277
285public:
286 enum class Scope : std::uint8_t {
287 Message,
288 Topic,
289 };
290
291 PreparedNonce(const PreparedNonce&) = delete;
293
294 PreparedNonce(PreparedNonce&& other) noexcept;
295 PreparedNonce& operator=(PreparedNonce&& other) noexcept;
297
302 [[nodiscard]] const Nonce& public_nonce() const noexcept {
303 return nonce_;
304 }
305
312 [[nodiscard]] Scalar32 scalar() const {
313 return scalar_;
314 }
315
325 [[nodiscard]] static PreparedNonce from_parts(Scope scope, const Scalar32& scalar, const Nonce& nonce,
327
334 [[nodiscard]] Result<Signature> sign_message(const Bip340Key& signer,
335 std::span<const unsigned char> message,
336 purify_secp_context* secp_context) &&;
337
344 [[nodiscard]] Result<Signature> sign_topic_message(const Bip340Key& signer,
345 std::span<const unsigned char> message,
346 purify_secp_context* secp_context) &&;
347
348private:
351
352 void clear() noexcept;
353
354 Scope scope_{Scope::Message};
355 Scalar32 scalar_{};
356 Nonce nonce_{};
357 XOnly32 signer_pubkey_{};
358 XOnly32 binding_digest_{};
359};
360
362public:
365
369
374 [[nodiscard]] const Nonce& public_nonce() const noexcept {
375 return prepared_.public_nonce();
376 }
377
382 [[nodiscard]] const NonceProof& proof() const noexcept {
383 return proof_;
384 }
385
390 [[nodiscard]] Scalar32 scalar() const {
391 return prepared_.scalar();
392 }
393
400 [[nodiscard]] static PreparedNonceWithProof from_parts(PreparedNonce prepared, NonceProof proof);
401
408 [[nodiscard]] Result<ProvenSignature> sign_message(const SecretKey& secret,
409 std::span<const unsigned char> message,
410 purify_secp_context* secp_context) &&;
411
418 [[nodiscard]] Result<ProvenSignature> sign_topic_message(const SecretKey& secret,
419 std::span<const unsigned char> message,
420 purify_secp_context* secp_context) &&;
421
422private:
424 : prepared_(std::move(prepared)), proof_(std::move(proof)) {}
425
426 PreparedNonce prepared_;
427 NonceProof proof_;
428};
429
430class KeyPair {
431public:
432 KeyPair(const KeyPair&) = delete;
433 KeyPair& operator=(const KeyPair&) = delete;
434 KeyPair(KeyPair&& other) noexcept = default;
435 KeyPair& operator=(KeyPair&& other) noexcept = default;
436 ~KeyPair() = default;
437
443 [[nodiscard]] static Result<KeyPair> from_secret(const SecretKey& secret,
444 purify_secp_context* secp_context);
445
451 [[nodiscard]] static Result<KeyPair> from_secret(SecretKey&& secret,
452 purify_secp_context* secp_context);
453
458 [[nodiscard]] const PublicKey& public_key() const noexcept {
459 return public_key_;
460 }
461
467 [[nodiscard]] Result<PreparedNonce> prepare_message_nonce(std::span<const unsigned char> message,
468 purify_secp_context* secp_context) const;
469
477 std::span<const unsigned char> message,
478 purify_secp_context* secp_context,
479 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
480
488 const MessageProofCache& cache,
489 purify_secp_context* secp_context,
490 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
491
497 [[nodiscard]] Result<PreparedNonce> prepare_topic_nonce(std::span<const unsigned char> topic,
498 purify_secp_context* secp_context) const;
499
507 std::span<const unsigned char> topic,
508 purify_secp_context* secp_context,
509 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
510
518 const TopicProofCache& cache,
519 purify_secp_context* secp_context,
520 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
521
527 [[nodiscard]] Result<Signature> sign_message(std::span<const unsigned char> message,
528 purify_secp_context* secp_context) const;
529
536 [[nodiscard]] Result<Signature> sign_message_with_prepared(std::span<const unsigned char> message,
537 PreparedNonce&& prepared,
538 purify_secp_context* secp_context) const;
539
547 std::span<const unsigned char> message,
548 PreparedNonceWithProof&& prepared,
549 purify_secp_context* secp_context) const;
550
557 [[nodiscard]] Result<Signature> sign_with_topic(std::span<const unsigned char> message,
558 std::span<const unsigned char> topic,
559 purify_secp_context* secp_context) const;
566 [[nodiscard]] Result<Signature> sign_with_prepared_topic(std::span<const unsigned char> message,
567 PreparedNonce&& prepared,
568 purify_secp_context* secp_context) const;
569
577 std::span<const unsigned char> message,
578 PreparedNonceWithProof&& prepared,
579 purify_secp_context* secp_context) const;
580
588 std::span<const unsigned char> message,
589 purify_secp_context* secp_context,
590 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
591
599 const MessageProofCache& cache,
600 purify_secp_context* secp_context,
601 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
602
611 std::span<const unsigned char> message,
612 std::span<const unsigned char> topic,
613 purify_secp_context* secp_context,
614 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
615
624 std::span<const unsigned char> message,
625 const TopicProofCache& cache,
626 purify_secp_context* secp_context,
627 bppp::ExperimentalCircuitBackend* circuit_cache = nullptr) const;
628
629private:
631 : secret_(std::move(secret)), public_key_(std::move(public_key)) {}
632
633 SecretKey secret_;
634 PublicKey public_key_{};
635};
636
637} // namespace purify::puresign_plusplus
High-level Purify key generation, evaluation, witness generation, and circuit helpers.
C++ wrappers for the BPPP functionality used by Purify.
Purify result carrier that either holds a value or an error.
Definition expected.hpp:64
Public-key-agnostic native verifier-circuit template.
Move-only packed Purify secret stored in dedicated heap memory.
Definition secret.hpp:52
Common interface for reusable experimental BPPP backend state.
Definition bppp.hpp:119
Caller-owned cache for reusable experimental circuit reduction and BPPP backend data.
Definition bppp.hpp:186
Result< PreparedNonce > prepare_message_nonce(std::span< const unsigned char > message, purify_secp_context *secp_context) const
Deterministically prepares a message-bound nonce.
Definition bppp.cpp:808
Result< PreparedNonce > prepare_topic_nonce(std::span< const unsigned char > topic, purify_secp_context *secp_context) const
Deterministically prepares a topic-bound nonce.
Definition bppp.cpp:827
Result< ProvenSignature > sign_message_with_proof(std::span< const unsigned char > message, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Signs a message and returns the signature bundled with its BPPP nonce proof.
Definition bppp.cpp:885
const PublicKey & public_key() const noexcept
Returns the public key bundle associated with this signer.
Definition bppp.hpp:458
Result< Signature > sign_with_prepared_topic(std::span< const unsigned char > message, PreparedNonce &&prepared, purify_secp_context *secp_context) const
Signs a message using an already prepared topic-bound nonce.
Definition bppp.cpp:872
KeyPair & operator=(KeyPair &&other) noexcept=default
KeyPair & operator=(const KeyPair &)=delete
static Result< KeyPair > from_secret(const SecretKey &secret, purify_secp_context *secp_context)
Derives a PureSign++ signing key pair from one packed Purify secret.
Definition bppp.cpp:798
Result< PreparedNonceWithProof > prepare_message_nonce_with_proof(std::span< const unsigned char > message, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Deterministically prepares a message-bound nonce together with its BPPP proof.
Definition bppp.cpp:813
Result< ProvenSignature > sign_with_prepared_topic_proof(std::span< const unsigned char > message, PreparedNonceWithProof &&prepared, purify_secp_context *secp_context) const
Signs a message using an already prepared topic-bound nonce proof bundle.
Definition bppp.cpp:879
Result< Signature > sign_message_with_prepared(std::span< const unsigned char > message, PreparedNonce &&prepared, purify_secp_context *secp_context) const
Signs a message using an already prepared message-bound nonce.
Definition bppp.cpp:852
Result< ProvenSignature > sign_with_topic_proof(std::span< const unsigned char > message, std::span< const unsigned char > topic, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Signs a message with a topic-bound nonce proof.
Definition bppp.cpp:901
Result< Signature > sign_message(std::span< const unsigned char > message, purify_secp_context *secp_context) const
Signs a message with a deterministically derived message-bound nonce.
Definition bppp.cpp:846
Result< PreparedNonceWithProof > prepare_topic_nonce_with_proof(std::span< const unsigned char > topic, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Deterministically prepares a topic-bound nonce together with its BPPP proof.
Definition bppp.cpp:832
KeyPair(const KeyPair &)=delete
Result< Signature > sign_with_topic(std::span< const unsigned char > message, std::span< const unsigned char > topic, purify_secp_context *secp_context) const
Signs a message using a topic-bound deterministic nonce.
Definition bppp.cpp:865
KeyPair(KeyPair &&other) noexcept=default
Result< ProvenSignature > sign_message_with_prepared_proof(std::span< const unsigned char > message, PreparedNonceWithProof &&prepared, purify_secp_context *secp_context) const
Signs a message using an already prepared message-bound nonce proof bundle.
Definition bppp.cpp:859
PreparedNonceWithProof(const PreparedNonceWithProof &)=delete
const NonceProof & proof() const noexcept
Returns the public nonce proof carried by this bundle.
Definition bppp.hpp:382
Result< ProvenSignature > sign_message(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context) &&
Consumes this message-bound prepared proof bundle and signs the message.
Definition bppp.cpp:400
static PreparedNonceWithProof from_parts(PreparedNonce prepared, NonceProof proof)
Bundles a prepared nonce with its matching BPPP-backed public nonce proof.
Definition bppp.cpp:396
PreparedNonceWithProof & operator=(PreparedNonceWithProof &&other) noexcept=default
Scalar32 scalar() const
Explicitly exports the secret nonce scalar from the wrapped prepared nonce.
Definition bppp.hpp:390
PreparedNonceWithProof(PreparedNonceWithProof &&other) noexcept=default
Result< ProvenSignature > sign_topic_message(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context) &&
Consumes this topic-bound prepared proof bundle and signs the message.
Definition bppp.cpp:413
const Nonce & public_nonce() const noexcept
Returns the public nonce proved by this bundle.
Definition bppp.hpp:374
PreparedNonceWithProof & operator=(const PreparedNonceWithProof &)=delete
Move-only prepared nonce bound to either a message or a topic.
Definition bppp.hpp:284
Result< Signature > sign_message(const Bip340Key &signer, std::span< const unsigned char > message, purify_secp_context *secp_context) &&
Consumes this message-bound nonce and signs the matching message.
Definition bppp.cpp:338
const Nonce & public_nonce() const noexcept
Returns the public nonce corresponding to this prepared secret nonce scalar.
Definition bppp.hpp:302
PreparedNonce & operator=(const PreparedNonce &)=delete
PreparedNonce(const PreparedNonce &)=delete
Result< Signature > sign_topic_message(const Bip340Key &signer, std::span< const unsigned char > message, purify_secp_context *secp_context) &&
Consumes this topic-bound nonce and signs a message under that topic binding.
Definition bppp.cpp:368
Scalar32 scalar() const
Explicitly exports the secret nonce scalar.
Definition bppp.hpp:312
static PreparedNonce from_parts(Scope scope, const Scalar32 &scalar, const Nonce &nonce, const XOnly32 &signer_pubkey, const XOnly32 &binding_digest)
Builds a prepared nonce from already-derived nonce components.
Definition bppp.cpp:306
std::array< unsigned char, 33 > PointBytes
Compressed 33-byte curve-point encoding.
Definition bppp.hpp:32
std::array< unsigned char, 64 > Signature64
Definition bppp.hpp:24
std::array< unsigned char, 32 > Scalar32
Definition bppp.hpp:22
std::array< unsigned char, 32 > XOnly32
Definition bppp.hpp:23
std::vector< unsigned char > Bytes
Dynamically sized byte string used for messages, serialized witnesses, and proofs.
Definition common.hpp:99
Scope scope
Definition bppp.cpp:118
Nonce nonce
Definition bppp.cpp:120
XOnly32 signer_pubkey
Definition bppp.cpp:121
XOnly32 binding_digest
Definition bppp.cpp:122
Canonical BIP340 keypair derived deterministically from a packed Purify secret.
Definition api.hpp:38
Experimental masked circuit proof that hides the reduced witness before the final BPPP argument.
Definition bppp.hpp:257
Cacheable message-bound nonce-proof template for the BPPP-backed PureSign++ proof(R) flow.
Definition bppp.hpp:218
bppp::ExperimentalCircuitCache backend_cache
Definition bppp.hpp:223
NativeBulletproofCircuitTemplate circuit_template
Definition bppp.hpp:221
static Result< MessageProofCache > build(std::span< const unsigned char > message)
Builds a reusable verifier template for one exact message.
Definition bppp.cpp:271
static Result< NonceProof > deserialize(std::span< const unsigned char > serialized, purify_secp_context *secp_context)
Definition bppp.cpp:144
Result< Bytes > serialize(purify_secp_context *secp_context) const
Definition bppp.cpp:117
bppp::ExperimentalCircuitZkNormArgProof proof
Definition bppp.hpp:260
static constexpr unsigned char kSerializationVersion
Definition bppp.hpp:256
Public BIP340 nonce point in x-only form.
Definition bppp.hpp:182
static Result< Nonce > deserialize(std::span< const unsigned char > serialized, purify_secp_context *secp_context)
Parses a serialized x-only nonce.
Definition bppp.cpp:71
Bytes serialize() const
Serializes this x-only nonce into its fixed-size wire format.
Definition bppp.cpp:67
static constexpr std::size_t kSerializedSize
Definition bppp.hpp:183
Result< Bytes > serialize(purify_secp_context *secp_context) const
Definition bppp.cpp:180
static constexpr unsigned char kSerializationVersion
Definition bppp.hpp:268
static Result< ProvenSignature > deserialize(std::span< const unsigned char > serialized, purify_secp_context *secp_context)
Definition bppp.cpp:200
static Result< PublicKey > from_secret(const SecretKey &secret, purify_secp_context *secp_context)
Derives both public identities from one packed Purify secret.
Definition bppp.cpp:733
Result< bool > verify_message_nonce_proof(std::span< const unsigned char > message, const NonceProof &nonce_proof, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Verifies a message-bound BPPP nonce proof against this public key.
Definition bppp.cpp:742
static Result< PublicKey > deserialize(std::span< const unsigned char > serialized, purify_secp_context *secp_context)
Parses a serialized PureSign++ public-key bundle.
Definition bppp.cpp:49
Result< bool > verify_topic_nonce_proof(std::span< const unsigned char > topic, const NonceProof &nonce_proof, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Verifies a topic-bound BPPP nonce proof against this public key.
Definition bppp.cpp:755
Result< bool > verify_signature(std::span< const unsigned char > message, const Signature &signature, purify_secp_context *secp_context) const
Verifies a plain BIP340 signature against this bundle's x-only public key.
Definition bppp.cpp:737
Bytes serialize() const
Serializes this PureSign++ public-key bundle into its fixed-size wire format.
Definition bppp.cpp:40
Result< bool > verify_message_signature_with_proof(std::span< const unsigned char > message, const ProvenSignature &signature, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Verifies a message signature bundled with its BPPP nonce proof.
Definition bppp.cpp:768
static constexpr std::size_t kSerializedSize
Definition bppp.hpp:35
Result< bool > verify_topic_signature_with_proof(std::span< const unsigned char > message, std::span< const unsigned char > topic, const ProvenSignature &signature, purify_secp_context *secp_context, bppp::ExperimentalCircuitBackend *circuit_cache=nullptr) const
Verifies a topic-bound signature bundled with its BPPP nonce proof.
Definition bppp.cpp:782
Standard 64-byte BIP340 signature.
Definition bppp.hpp:195
Bytes serialize() const
Serializes this signature into its fixed-size wire format.
Definition bppp.cpp:98
static constexpr std::size_t kSerializedSize
Definition bppp.hpp:196
Scalar32 s() const
Returns the 32-byte Schnorr s scalar encoded in the last 32 signature bytes.
Definition bppp.cpp:92
Nonce nonce() const
Returns the x-only public nonce encoded in the first 32 signature bytes.
Definition bppp.cpp:86
static Result< Signature > deserialize(std::span< const unsigned char > serialized, purify_secp_context *secp_context)
Parses a serialized BIP340 signature.
Definition bppp.cpp:102
Cacheable topic-bound nonce-proof template for the BPPP-backed PureSign++ proof(R) flow.
Definition bppp.hpp:240
bppp::ExperimentalCircuitCache backend_cache
Definition bppp.hpp:245
NativeBulletproofCircuitTemplate circuit_template
Definition bppp.hpp:243
static Result< TopicProofCache > build(std::span< const unsigned char > topic)
Builds a reusable verifier template for one exact topic.
Definition bppp.cpp:285