33constexpr std::string_view kMessageNonceTag =
"PureSign/Nonce/Message/";
34constexpr std::string_view kTopicNonceTag =
"PureSign/Nonce/Topic/";
35constexpr std::string_view kMessageBindingTag =
"PureSign/Binding/Message";
36constexpr std::string_view kTopicBindingTag =
"PureSign/Binding/Topic";
37constexpr std::string_view kMessageProofTag =
"PureSign/Proof/Message/V1";
38constexpr std::string_view kTopicProofTag =
"PureSign/Proof/Topic/V1";
39const TaggedHash kMessageBindingTaggedHash(kMessageBindingTag);
40const TaggedHash kTopicBindingTaggedHash(kTopicBindingTag);
41const TaggedHash kMessageProofTaggedHash(kMessageProofTag);
42const TaggedHash kTopicProofTaggedHash(kTopicProofTag);
52const UInt256& secp256k1_order() {
54 UInt256::from_hex(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
58Status validate_puresign_field_alignment() {
67 "puresign:validate_public_key_bundle:purify_pubkey");
69 "puresign:validate_public_key_bundle:secp_context");
76const unsigned char* nullable_data(std::span<const unsigned char> input) {
77 return input.empty() ? nullptr : input.data();
80XOnly32 binding_digest(
const TaggedHash& tag, std::span<const unsigned char> input) {
82 out = tag.digest(input);
95 std::array<unsigned char, 64> secret_bytes = secret.packed().to_bytes_be();
97 std::array digest_segments{
98 std::span<const unsigned char>(secret_bytes.data(), secret_bytes.size()),
101 out = proof_tagged_hash(scope).digest_many(digest_segments);
110 "nonce_proof_matches_nonce:secp_context");
115 return xonly == nonce_proof.nonce.xonly;
126struct DerivedNonceData {
135Result<NonceProof> build_nonce_proof_from_template(
const SecretKey& secret,
const DerivedNonceData& nonce_data,
136 const NativeBulletproofCircuitTemplate& circuit_template,
138 ExperimentalBulletproofBackendCache* backend_cache =
nullptr) {
140 "build_nonce_proof_from_template:prove_assignment_data");
142 "build_nonce_proof_from_template:partial_evaluate");
146 PURIFY_ASSIGN_OR_RETURN(
auto final_ok, circuit_template.final_evaluate(witness.assignment, witness.public_key),
147 "build_nonce_proof_from_template:final_evaluate");
152 "build_nonce_proof_from_template:instantiate_packed");
154 "build_nonce_proof_from_template:validate_proof_cache_circuit");
156 Scalar32 proof_nonce = derive_proof_nonce_seed(secret, nonce_data.scope, nonce_data.eval_input);
157 Bytes statement_binding = proof_statement_binding(nonce_data.scope);
162 statement_binding, std::nullopt,
164 "build_nonce_proof_from_template:prove_experimental_circuit");
167 out.
nonce = nonce_data.nonce;
168 out.proof = std::move(proof);
170 "build_nonce_proof_from_template:nonce_proof_matches_nonce");
178 std::span<const unsigned char> input,
180 PURIFY_RETURN_IF_ERROR(validate_puresign_field_alignment(),
"derive_nonce_data:validate_puresign_field_alignment");
184 const TaggedHash& binding_hash = binding_tagged_hash(scope);
186 DerivedNonceData out{};
188 out.signer_pubkey = signer.xonly_pubkey;
189 out.binding_digest = binding_digest(binding_hash, input);
193 out.scalar = nonce_value.to_bytes_be();
194 if (std::all_of(out.scalar.begin(), out.scalar.end(), [](
unsigned char byte) { return byte == 0; })) {
203 "derive_nonce_data:secp_context");
211 const DerivedNonceData& nonce_data,
214 "build_nonce_proof:verifier_circuit_template");
215 return build_nonce_proof_from_template(secret, nonce_data, circuit_template, secp_context);
219 std::span<const unsigned char> input,
225 "prepare_nonce_data_impl:derive_nonce_data");
229Result<bool> verify_nonce_proof_with_circuit(
const PublicKey& public_key,
const NativeBulletproofCircuit& circuit,
233 ExperimentalBulletproofBackendCache* backend_cache =
nullptr) {
240 Bytes statement_binding = proof_statement_binding(scope);
246 const NativeBulletproofCircuit::PackedWithSlack& circuit,
250 ExperimentalBulletproofBackendCache* backend_cache =
nullptr) {
257 Bytes statement_binding = proof_statement_binding(scope);
266 : scope_(scope), scalar_(scalar), nonce_(nonce), signer_pubkey_(signer_pubkey), binding_digest_(binding_digest) {}
274 : scope_(other.scope_), scalar_(other.scalar_), nonce_(other.nonce_),
275 signer_pubkey_(other.signer_pubkey_), binding_digest_(other.binding_digest_) {
280 if (
this != &other) {
282 scope_ = other.scope_;
283 scalar_ = other.scalar_;
284 nonce_ = other.nonce_;
285 signer_pubkey_ = other.signer_pubkey_;
286 binding_digest_ = other.binding_digest_;
296void PreparedNonce::clear() noexcept {
297 std::fill(scalar_.begin(), scalar_.end(),
static_cast<unsigned char>(0));
301 std::span<const unsigned char> message,
306 if (signer_pubkey_ != signer.xonly_pubkey) {
309 if (binding_digest_ != binding_digest(kMessageBindingTaggedHash, message)) {
314 "PreparedNonce::sign_message:secp_context");
317 signer.seckey.data(), scalar_.data()) == 0) {
324 signer.xonly_pubkey.data()) == 0) {
331 std::span<const unsigned char> message,
336 if (signer_pubkey_ != signer.xonly_pubkey) {
341 "PreparedNonce::sign_topic_message:secp_context");
344 signer.seckey.data(), scalar_.data()) == 0) {
346 "PreparedNonce::sign_topic_message:sign_with_fixed_nonce");
352 signer.xonly_pubkey.data()) == 0) {
363 std::span<const unsigned char> message,
368 "PreparedNonceWithProof::sign_message:sign_message_with_prepared");
369 if (signature.nonce().xonly != nonce_proof.
nonce.
xonly) {
376 std::span<const unsigned char> message,
381 "PreparedNonceWithProof::sign_topic_message:sign_with_prepared_topic");
382 if (signature.nonce().xonly != nonce_proof.
nonce.
xonly) {
393 return PublicKey{purify_key.public_key, bip340_key.xonly_pubkey};
399 "build_message_proof_cache:verifier_circuit_template");
401 "build_message_proof_cache:integrity_digest");
416 "build_topic_proof_cache:verifier_circuit_template");
418 "build_topic_proof_cache:integrity_digest");
431 "prepare_message_nonce:prepare_nonce_data_impl");
433 nonce_data.signer_pubkey, nonce_data.binding_digest);
437 std::span<const unsigned char> message,
441 "prepare_message_nonce_with_proof:prepare_nonce_data_impl");
443 nonce_data.nonce, nonce_data.signer_pubkey,
444 nonce_data.binding_digest);
446 "prepare_message_nonce_with_proof:build_nonce_proof");
454 "prepare_message_nonce_with_proof:validate_message_proof_cache");
457 "prepare_message_nonce_with_proof:prepare_nonce_data_impl");
459 nonce_data.nonce, nonce_data.signer_pubkey,
460 nonce_data.binding_digest);
462 build_nonce_proof_from_template(secret, nonce_data, cache.
circuit_template, secp_context,
464 "prepare_message_nonce_with_proof:build_nonce_proof_from_template");
472 "prepare_topic_nonce:prepare_nonce_data_impl");
474 nonce_data.signer_pubkey, nonce_data.binding_digest);
478 std::span<const unsigned char> topic,
482 "prepare_topic_nonce_with_proof:prepare_nonce_data_impl");
484 nonce_data.nonce, nonce_data.signer_pubkey,
485 nonce_data.binding_digest);
487 "prepare_topic_nonce_with_proof:build_nonce_proof");
495 "prepare_topic_nonce_with_proof:validate_topic_proof_cache");
498 "prepare_topic_nonce_with_proof:prepare_nonce_data_impl");
500 nonce_data.nonce, nonce_data.signer_pubkey,
501 nonce_data.binding_digest);
503 build_nonce_proof_from_template(secret, nonce_data, cache.
circuit_template, secp_context,
505 "prepare_topic_nonce_with_proof:build_nonce_proof_from_template");
518 return std::move(prepared).sign_message(signer, message, secp_context);
524 return std::move(prepared).sign_message(secret, message, secp_context);
528 std::span<const unsigned char> topic,
537 return std::move(prepared).sign_topic_message(signer, message, secp_context);
543 return std::move(prepared).sign_topic_message(secret, message, secp_context);
549 "sign_message_with_proof:prepare_message_nonce_with_proof");
556 "sign_message_with_proof:prepare_message_nonce_with_proof_cache");
561 std::span<const unsigned char> topic,
564 "sign_with_topic_proof:prepare_topic_nonce_with_proof");
572 "sign_with_topic_proof:prepare_topic_nonce_with_proof_cache");
580 "verify_signature:secp_context");
597 "verify_message_nonce_proof:verifier_circuit");
599 "verify_message_nonce_proof:verify_nonce_proof_with_circuit",
607 PURIFY_RETURN_IF_ERROR(validate_message_proof_cache(cache),
"verify_message_nonce_proof:validate_message_proof_cache");
609 "verify_message_nonce_proof:instantiate_packed");
611 "verify_message_nonce_proof:verify_nonce_proof_with_circuit",
612 circuit_cache !=
nullptr ? circuit_cache : &cache.
backend_cache);
624 "verify_topic_nonce_proof:verifier_circuit");
626 "verify_topic_nonce_proof:verify_nonce_proof_with_circuit",
634 PURIFY_RETURN_IF_ERROR(validate_topic_proof_cache(cache),
"verify_topic_nonce_proof:validate_topic_proof_cache");
636 "verify_topic_nonce_proof:instantiate_packed");
638 "verify_topic_nonce_proof:verify_nonce_proof_with_circuit",
639 circuit_cache !=
nullptr ? circuit_cache : &cache.
backend_cache);
647 "verify_message_signature_with_proof:verify_signature");
662 "verify_message_signature_with_proof:verify_signature");
673 std::span<const unsigned char> topic,
678 "verify_topic_signature_with_proof:verify_signature");
689 std::span<const unsigned char> message,
694 "verify_topic_signature_with_proof:verify_signature");
756 std::span<const unsigned char> topic,
764 std::span<const unsigned char> message,
829 return std::move(prepared).sign_message(signer, message, secp_context);
835 return std::move(prepared).sign_message(secret_, message, secp_context);
839 std::span<const unsigned char> topic,
849 return std::move(prepared).sign_topic_message(signer, message, secp_context);
855 return std::move(prepared).sign_topic_message(secret_, message, secp_context);
861 "KeyPair::sign_message_with_proof:prepare_message_nonce_with_proof");
868 "KeyPair::sign_message_with_proof:prepare_message_nonce_with_proof");
873 std::span<const unsigned char> topic,
876 "KeyPair::sign_with_topic_proof:prepare_topic_nonce_with_proof");
884 "KeyPair::sign_with_topic_proof:prepare_topic_nonce_with_proof");
C++ wrappers for the BPPP functionality used by Purify.
Caller-owned cache for reusable legacy Bulletproof backend resources keyed by gate count.
Result< NativeBulletproofCircuit::PackedWithSlack > instantiate_packed(const UInt512 &pubkey) const
Move-only packed Purify secret stored in dedicated heap memory.
Result< SecretKey > clone() const
Creates a second owned copy of this secret key.
Reusable BIP340-style tagged SHA-256 helper.
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.
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.
static Result< KeyPair > from_secret(const SecretKey &secret, purify_secp_context *secp_context)
Derives a signing key pair from one packed Purify secret.
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.
Result< PreparedNonce > prepare_message_nonce(std::span< const unsigned char > message, purify_secp_context *secp_context) const
Deterministically prepares a message-bound nonce.
Result< PreparedNonceWithProof > prepare_message_nonce_with_proof(std::span< const unsigned char > message, purify_secp_context *secp_context) const
Deterministically prepares a message-bound nonce together with its proof.
Result< PreparedNonce > prepare_topic_nonce(std::span< const unsigned char > topic, purify_secp_context *secp_context) const
Deterministically prepares a topic-bound nonce.
Result< PreparedNonceWithProof > prepare_topic_nonce_with_proof(std::span< const unsigned char > topic, purify_secp_context *secp_context) const
Deterministically prepares a topic-bound nonce together with its proof.
KeyPair(const KeyPair &)=delete
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.
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.
Result< ProvenSignature > sign_with_topic_proof(std::span< const unsigned char > message, std::span< const unsigned char > topic, purify_secp_context *secp_context) const
Signs a message with a topic-bound nonce proof.
const PublicKey & public_key() const noexcept
Returns the public key bundle associated with this signer.
Result< ProvenSignature > sign_message_with_proof(std::span< const unsigned char > message, purify_secp_context *secp_context) const
Signs a message and returns the signature bundled with its nonce proof.
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.
Move-only prepared nonce bundled with its public statement proof.
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.
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.
const NonceProof & proof() const noexcept
Returns the public nonce proof carried by this bundle.
static PreparedNonceWithProof from_parts(PreparedNonce prepared, NonceProof proof)
Bundles a prepared nonce with its matching public nonce proof.
PreparedNonceWithProof(const PreparedNonceWithProof &)=delete
Move-only prepared nonce bound to either a message or a topic.
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.
Scalar32 scalar() const
Explicitly exports the secret nonce scalar.
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.
PreparedNonce & operator=(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.
PreparedNonce(const PreparedNonce &)=delete
Elliptic-curve helpers, fixed parameters, and hash-to-curve utilities for Purify.
#define PURIFY_RETURN_IF_ERROR(expr, context)
Evaluates an expected-like expression and returns the wrapped error on failure.
#define PURIFY_ASSIGN_OR_RETURN(lhs, expr, context)
Evaluates an expected-like expression, binds the value to lhs, and propagates errors.
Legacy Bulletproof-backed Purify-derived BIP340 signing helpers with prepared nonces.
GeneratorBytes base_generator(purify_secp_context *secp_context)
Returns the serialized secp256k1 base generator used as the blind generator.
const UInt256 & secp256k1_order()
Bytes tagged_eval_input(std::string_view tag, std::span< const unsigned char > input)
Status validate_topic_proof_cache(const CacheLike &cache, std::string_view nonce_tag)
void secure_clear_bytes(void *data, std::size_t size) noexcept
Status validate_message_proof_cache(const CacheLike &cache, std::string_view nonce_tag)
Bytes copy_bytes(std::span< const unsigned char > input)
Status validate_proof_cache_circuit(const CircuitLike &circuit, const char *context)
Result< PreparedNonce > prepare_topic_nonce(const SecretKey &secret, std::span< const unsigned char > topic, purify_secp_context *secp_context)
Result< ProvenSignature > sign_message_with_prepared_proof(const SecretKey &secret, std::span< const unsigned char > message, PreparedNonceWithProof &&prepared, purify_secp_context *secp_context)
Result< ProvenSignature > sign_message_with_proof(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context)
Result< PreparedNonceWithProof > prepare_topic_nonce_with_proof(const SecretKey &secret, std::span< const unsigned char > topic, purify_secp_context *secp_context)
Result< Signature > sign_message(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context)
Result< ProvenSignature > sign_with_prepared_topic_proof(const SecretKey &secret, std::span< const unsigned char > message, PreparedNonceWithProof &&prepared, purify_secp_context *secp_context)
Result< TopicProofCache > build_topic_proof_cache(std::span< const unsigned char > topic)
Result< bool > verify_topic_nonce_proof(const PublicKey &public_key, std::span< const unsigned char > topic, const NonceProof &nonce_proof, purify_secp_context *secp_context, ExperimentalBulletproofBackendCache *circuit_cache)
Result< PreparedNonceWithProof > prepare_message_nonce_with_proof(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context)
Result< bool > verify_message_nonce_proof(const PublicKey &public_key, std::span< const unsigned char > message, const NonceProof &nonce_proof, purify_secp_context *secp_context, ExperimentalBulletproofBackendCache *circuit_cache)
Result< Signature > sign_with_topic(const SecretKey &secret, std::span< const unsigned char > message, std::span< const unsigned char > topic, purify_secp_context *secp_context)
Result< bool > verify_topic_signature_with_proof(const PublicKey &public_key, std::span< const unsigned char > message, std::span< const unsigned char > topic, const ProvenSignature &signature, purify_secp_context *secp_context, ExperimentalBulletproofBackendCache *circuit_cache)
Result< Signature > sign_message_with_prepared(const SecretKey &secret, std::span< const unsigned char > message, PreparedNonce &&prepared, purify_secp_context *secp_context)
Result< bool > verify_message_signature_with_proof(const PublicKey &public_key, std::span< const unsigned char > message, const ProvenSignature &signature, purify_secp_context *secp_context, ExperimentalBulletproofBackendCache *circuit_cache)
Result< PreparedNonce > prepare_message_nonce(const SecretKey &secret, std::span< const unsigned char > message, purify_secp_context *secp_context)
Result< PublicKey > derive_public_key(const SecretKey &secret, purify_secp_context *secp_context)
Result< ProvenSignature > sign_with_topic_proof(const SecretKey &secret, std::span< const unsigned char > message, std::span< const unsigned char > topic, purify_secp_context *secp_context)
Result< MessageProofCache > build_message_proof_cache(std::span< const unsigned char > message)
Result< bool > verify_signature(const PublicKey &public_key, std::span< const unsigned char > message, const Signature &signature, purify_secp_context *secp_context)
Result< Signature > sign_with_prepared_topic(const SecretKey &secret, std::span< const unsigned char > message, PreparedNonce &&prepared, purify_secp_context *secp_context)
std::array< unsigned char, 32 > Scalar32
std::array< unsigned char, 32 > XOnly32
Status require_secp_context(const purify_secp_context *context, const char *error_context)
constexpr Unexpected< Error > unexpected_error(ErrorCode code, const char *context=nullptr)
Constructs an unexpected Error value from a machine-readable code.
const UInt256 & prime_p()
Returns the Purify base-field modulus.
Result< NativeBulletproofCircuitTemplate > verifier_circuit_template(const Bytes &message)
Builds a reusable public-key-agnostic verifier-circuit template for a message.
Result< BulletproofWitnessData > prove_assignment_data(const Bytes &message, const SecretKey &secret)
Computes the native Purify witness for a message and secret.
Result< bool > verify_experimental_circuit(const NativeBulletproofCircuit &circuit, const ExperimentalBulletproofProof &proof, const BulletproofGeneratorBytes &value_generator, purify_secp_context *secp_context, std::span< const unsigned char > statement_binding={}, ExperimentalBulletproofBackendCache *backend_cache=nullptr)
Verifies a proof produced by prove_experimental_circuit against the same one-commitment native circui...
Result< NativeBulletproofCircuit > verifier_circuit(const Bytes &message, const UInt512 &pubkey)
Builds the native verifier circuit for a message and public key.
Bytes bytes_from_ascii(std::string_view input)
Encodes an ASCII string as a byte vector.
BigUInt< 4 > UInt256
256-bit unsigned integer used for field elements and curve orders.
Status validate_public_key(const UInt512 &packed)
Validates the packed public-key encoding range.
Result< Bip340Key > derive_bip340_key(const SecretKey &secret, purify_secp_context *secp_context)
Derives a canonical BIP340 signing keypair from an owned Purify secret.
Result< GeneratedKey > derive_key(const SecretKey &secret)
Derives the packed public key corresponding to a packed secret.
Expected< T, Error > Result
Expected-returning convenience alias for Purify value-producing APIs.
Result< FieldElement > eval(const SecretKey &secret, const Bytes &message)
Evaluates the Purify PRF for an owned secret key and message.
Expected< void, Error > Status
Expected-returning convenience alias for Purify status-only APIs.
std::vector< unsigned char > Bytes
Dynamically sized byte string used for messages, serialized witnesses, and proofs.
Result< ExperimentalBulletproofProof > prove_experimental_circuit_assume_valid(const NativeBulletproofCircuit::PackedWithSlack &circuit, const BulletproofAssignmentData &assignment, const BulletproofScalarBytes &nonce, const BulletproofGeneratorBytes &value_generator, purify_secp_context *secp_context, std::span< const unsigned char > statement_binding, std::optional< BulletproofScalarBytes > blind, ExperimentalBulletproofBackendCache *backend_cache)
int purify_bip340_xonly_from_point(purify_secp_context *context, const unsigned char point33[33], unsigned char xonly32[32], int *parity_out)
Converts a compressed secp256k1 point into its x-only public key encoding.
int purify_bip340_nonce_from_scalar(purify_secp_context *context, unsigned char scalar32[32], unsigned char xonly_nonce32[32])
Canonicalizes a valid secp256k1 nonce scalar for BIP340 and derives its x-only public nonce.
int purify_bip340_sign_with_fixed_nonce(purify_secp_context *context, unsigned char sig64[64], const unsigned char *msg, size_t msglen, const unsigned char seckey32[32], const unsigned char nonce32[32])
Signs a message with a caller-supplied BIP340 nonce scalar.
int purify_bip340_validate_signature(purify_secp_context *context, const unsigned char sig64[64])
Returns nonzero when the 64-byte BIP340 signature has a syntactically valid encoding.
int purify_bip340_validate_xonly_pubkey(purify_secp_context *context, const unsigned char xonly_pubkey32[32])
Returns nonzero when the x-only public key encoding parses successfully.
int purify_bip340_verify(purify_secp_context *context, const unsigned char sig64[64], const unsigned char *msg, size_t msglen, const unsigned char xonly_pubkey32[32])
Verifies a BIP340 signature against a serialized x-only public key.
struct purify_secp_context purify_secp_context
Caller-owned reusable secp256k1 context handle shared across Purify C and C++ APIs.
static BigUInt from_hex(std::string_view hex)
Canonical BIP340 keypair derived deterministically from a packed Purify secret.
Cacheable message-bound nonce-proof template.
NativeBulletproofCircuitTemplate circuit_template
static Result< MessageProofCache > build(std::span< const unsigned char > message)
Builds a reusable verifier template for one exact message.
ExperimentalBulletproofBackendCache backend_cache
Public nonce together with its experimental Purify statement proof.
Public BIP340 nonce point in x-only form.
Standard signature bundled with the public nonce proof it relied on.
Public key bundle pairing a Purify packed public key with its derived BIP340 x-only key.
Result< bool > verify_message_signature_with_proof(std::span< const unsigned char > message, const ProvenSignature &signature, purify_secp_context *secp_context, ExperimentalBulletproofBackendCache *circuit_cache=nullptr) const
Verifies a message signature bundled with its nonce proof.
Result< bool > verify_message_nonce_proof(std::span< const unsigned char > message, const NonceProof &nonce_proof, purify_secp_context *secp_context, ExperimentalBulletproofBackendCache *circuit_cache=nullptr) const
Verifies a message-bound nonce proof against this public key.
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.
static Result< PublicKey > from_secret(const SecretKey &secret, purify_secp_context *secp_context)
Derives both public identities from one packed Purify secret.
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, ExperimentalBulletproofBackendCache *circuit_cache=nullptr) const
Verifies a topic-bound signature bundled with its nonce proof.
Result< bool > verify_topic_nonce_proof(std::span< const unsigned char > topic, const NonceProof &nonce_proof, purify_secp_context *secp_context, ExperimentalBulletproofBackendCache *circuit_cache=nullptr) const
Verifies a topic-bound nonce proof against this public key.
Standard 64-byte BIP340 signature.
Cacheable topic-bound nonce-proof template.
NativeBulletproofCircuitTemplate circuit_template
ExperimentalBulletproofBackendCache backend_cache
static Result< TopicProofCache > build(std::span< const unsigned char > topic)
Builds a reusable verifier template for one exact topic.