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();
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);
106Result<bool> nonce_proof_matches_nonce(
const NonceProof& nonce_proof,
purify_secp_context* secp_context) {
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;
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");
210Result<NonceProof> build_nonce_proof(
const SecretKey& secret,
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);
245Result<bool> verify_nonce_proof_with_circuit(
const PublicKey& public_key,
246 const NativeBulletproofCircuit::PackedWithSlack& circuit,
250 ExperimentalBulletproofBackendCache* backend_cache =
nullptr) {
257 Bytes statement_binding = proof_statement_binding(
scope);
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_;
292PreparedNonce::~PreparedNonce() {
296void PreparedNonce::clear() noexcept {
297 std::fill(scalar_.begin(), scalar_.end(),
static_cast<unsigned char>(0));
301 std::span<const unsigned char> message,
303 if (scope_ != Scope::Message) {
304 return unexpected_error(ErrorCode::BindingMismatch,
"PreparedNonce::sign_message:scope");
306 if (signer_pubkey_ != signer.xonly_pubkey) {
307 return unexpected_error(ErrorCode::BindingMismatch,
"PreparedNonce::sign_message:signer_pubkey");
309 if (binding_digest_ !=
binding_digest(kMessageBindingTaggedHash, message)) {
310 return unexpected_error(ErrorCode::BindingMismatch,
"PreparedNonce::sign_message:message_binding");
314 "PreparedNonce::sign_message:secp_context");
317 signer.seckey.data(), scalar_.data()) == 0) {
318 return unexpected_error(ErrorCode::BackendRejectedInput,
"PreparedNonce::sign_message:sign_with_fixed_nonce");
320 if (out.nonce().xonly != nonce_.xonly) {
321 return unexpected_error(ErrorCode::InternalMismatch,
"PreparedNonce::sign_message:nonce_mismatch");
323 if (
purify_bip340_verify(secp_context, out.bytes.data(), nullable_data(message), message.size(),
324 signer.xonly_pubkey.data()) == 0) {
325 return unexpected_error(ErrorCode::InternalMismatch,
"PreparedNonce::sign_message:self_verify");
331 std::span<const unsigned char> message,
333 if (scope_ != Scope::Topic) {
334 return unexpected_error(ErrorCode::BindingMismatch,
"PreparedNonce::sign_topic_message:scope");
336 if (signer_pubkey_ != signer.xonly_pubkey) {
337 return unexpected_error(ErrorCode::BindingMismatch,
"PreparedNonce::sign_topic_message:signer_pubkey");
341 "PreparedNonce::sign_topic_message:secp_context");
344 signer.seckey.data(), scalar_.data()) == 0) {
346 "PreparedNonce::sign_topic_message:sign_with_fixed_nonce");
348 if (out.nonce().xonly != nonce_.xonly) {
349 return unexpected_error(ErrorCode::InternalMismatch,
"PreparedNonce::sign_topic_message:nonce_mismatch");
351 if (
purify_bip340_verify(secp_context, out.bytes.data(), nullable_data(message), message.size(),
352 signer.xonly_pubkey.data()) == 0) {
353 return unexpected_error(ErrorCode::InternalMismatch,
"PreparedNonce::sign_topic_message:self_verify");
363 std::span<const unsigned char> message,
367 api_impl::sign_message_with_prepared(secret, message, std::move(prepared_), secp_context),
368 "PreparedNonceWithProof::sign_message:sign_message_with_prepared");
369 if (signature.nonce().xonly != nonce_proof.
nonce.
xonly) {
370 return unexpected_error(ErrorCode::InternalMismatch,
"PreparedNonceWithProof::sign_message:nonce_mismatch");
376 std::span<const unsigned char> message,
380 api_impl::sign_with_prepared_topic(secret, message, std::move(prepared_), secp_context),
381 "PreparedNonceWithProof::sign_topic_message:sign_with_prepared_topic");
382 if (signature.nonce().xonly != nonce_proof.
nonce.
xonly) {
383 return unexpected_error(ErrorCode::InternalMismatch,
"PreparedNonceWithProof::sign_topic_message:nonce_mismatch");
393 return PublicKey{purify_key.public_key, bip340_key.xonly_pubkey};
397 Bytes eval_input = detail::tagged_eval_input(kMessageNonceTag, message);
399 "build_message_proof_cache:verifier_circuit_template");
401 "build_message_proof_cache:integrity_digest");
403 cache.
message = detail::copy_bytes(message);
405 cache.circuit_template = std::move(circuit_template);
406 cache.template_digest = std::move(template_digest);
412 return unexpected_error(ErrorCode::EmptyInput,
"build_topic_proof_cache:empty_topic");
416 "build_topic_proof_cache:verifier_circuit_template");
418 "build_topic_proof_cache:integrity_digest");
420 cache.
topic = detail::copy_bytes(topic);
422 cache.circuit_template = std::move(circuit_template);
423 cache.template_digest = std::move(template_digest);
430 prepare_nonce_data_impl(secret, PreparedNonce::Scope::Message, message, secp_context),
431 "prepare_message_nonce:prepare_nonce_data_impl");
432 return PreparedNonce::from_parts(PreparedNonce::Scope::Message, nonce_data.scalar, nonce_data.nonce,
433 nonce_data.signer_pubkey, nonce_data.binding_digest);
437 std::span<const unsigned char> message,
440 prepare_nonce_data_impl(secret, PreparedNonce::Scope::Message, message, secp_context),
441 "prepare_message_nonce_with_proof:prepare_nonce_data_impl");
442 PreparedNonce prepared = PreparedNonce::from_parts(PreparedNonce::Scope::Message, nonce_data.scalar,
443 nonce_data.nonce, nonce_data.signer_pubkey,
444 nonce_data.binding_digest);
446 "prepare_message_nonce_with_proof:build_nonce_proof");
447 return PreparedNonceWithProof::from_parts(std::move(prepared), std::move(proof));
454 "prepare_message_nonce_with_proof:validate_message_proof_cache");
456 prepare_nonce_data_impl(secret, PreparedNonce::Scope::Message, cache.
message, secp_context),
457 "prepare_message_nonce_with_proof:prepare_nonce_data_impl");
458 PreparedNonce prepared = PreparedNonce::from_parts(PreparedNonce::Scope::Message, nonce_data.scalar,
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");
465 return PreparedNonceWithProof::from_parts(std::move(prepared), std::move(proof));
471 prepare_nonce_data_impl(secret, PreparedNonce::Scope::Topic, topic, secp_context),
472 "prepare_topic_nonce:prepare_nonce_data_impl");
473 return PreparedNonce::from_parts(PreparedNonce::Scope::Topic, nonce_data.scalar, nonce_data.nonce,
474 nonce_data.signer_pubkey, nonce_data.binding_digest);
478 std::span<const unsigned char> topic,
481 prepare_nonce_data_impl(secret, PreparedNonce::Scope::Topic, topic, secp_context),
482 "prepare_topic_nonce_with_proof:prepare_nonce_data_impl");
483 PreparedNonce prepared = PreparedNonce::from_parts(PreparedNonce::Scope::Topic, nonce_data.scalar,
484 nonce_data.nonce, nonce_data.signer_pubkey,
485 nonce_data.binding_digest);
487 "prepare_topic_nonce_with_proof:build_nonce_proof");
488 return PreparedNonceWithProof::from_parts(std::move(prepared), std::move(proof));
495 "prepare_topic_nonce_with_proof:validate_topic_proof_cache");
497 prepare_nonce_data_impl(secret, PreparedNonce::Scope::Topic, cache.
topic, secp_context),
498 "prepare_topic_nonce_with_proof:prepare_nonce_data_impl");
499 PreparedNonce prepared = PreparedNonce::from_parts(PreparedNonce::Scope::Topic, nonce_data.scalar,
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");
506 return PreparedNonceWithProof::from_parts(std::move(prepared), std::move(proof));
511 PURIFY_ASSIGN_OR_RETURN(
auto prepared, prepare_message_nonce(secret, message, secp_context),
"sign_message:prepare_message_nonce");
512 return sign_message_with_prepared(secret, message, std::move(prepared), secp_context);
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,
530 PURIFY_ASSIGN_OR_RETURN(
auto prepared, prepare_topic_nonce(secret, topic, secp_context),
"sign_with_topic:prepare_topic_nonce");
531 return sign_with_prepared_topic(secret, message, std::move(prepared), secp_context);
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");
550 return sign_message_with_prepared_proof(secret, message, std::move(prepared), secp_context);
556 "sign_message_with_proof:prepare_message_nonce_with_proof_cache");
557 return sign_message_with_prepared_proof(secret, cache.
message, std::move(prepared), secp_context);
561 std::span<const unsigned char> topic,
564 "sign_with_topic_proof:prepare_topic_nonce_with_proof");
565 return sign_with_prepared_topic_proof(secret, message, std::move(prepared), secp_context);
572 "sign_with_topic_proof:prepare_topic_nonce_with_proof_cache");
573 return sign_with_prepared_topic_proof(secret, message, std::move(prepared), secp_context);
580 "verify_signature:secp_context");
582 return unexpected_error(ErrorCode::BackendRejectedInput,
"verify_signature:bip340_validate_xonly_pubkey");
585 return unexpected_error(ErrorCode::BackendRejectedInput,
"verify_signature:bip340_validate_signature");
597 "verify_message_nonce_proof:verifier_circuit");
598 return verify_nonce_proof_with_circuit(public_key, circuit, nonce_proof, PreparedNonce::Scope::Message, secp_context,
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");
610 return verify_nonce_proof_with_circuit(public_key, circuit, nonce_proof, PreparedNonce::Scope::Message, secp_context,
611 "verify_message_nonce_proof:verify_nonce_proof_with_circuit",
612 circuit_cache !=
nullptr ? circuit_cache : &cache.
backend_cache);
620 return unexpected_error(ErrorCode::EmptyInput,
"verify_topic_nonce_proof:empty_topic");
624 "verify_topic_nonce_proof:verifier_circuit");
625 return verify_nonce_proof_with_circuit(public_key, circuit, nonce_proof, PreparedNonce::Scope::Topic, secp_context,
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");
637 return verify_nonce_proof_with_circuit(public_key, circuit, nonce_proof, PreparedNonce::Scope::Topic, secp_context,
638 "verify_topic_nonce_proof:verify_nonce_proof_with_circuit",
639 circuit_cache !=
nullptr ? circuit_cache : &cache.
backend_cache);
642Result<bool> verify_message_signature_with_proof(
const PublicKey& public_key, std::span<const unsigned char> message,
647 "verify_message_signature_with_proof:verify_signature");
654 return verify_message_nonce_proof(public_key, message, signature.
nonce_proof, secp_context, circuit_cache);
662 "verify_message_signature_with_proof:verify_signature");
669 return verify_message_nonce_proof(cache, public_key, signature.
nonce_proof, secp_context, circuit_cache);
673 std::span<const unsigned char> topic,
678 "verify_topic_signature_with_proof:verify_signature");
685 return verify_topic_nonce_proof(public_key, topic, signature.
nonce_proof, secp_context, circuit_cache);
689 std::span<const unsigned char> message,
694 "verify_topic_signature_with_proof:verify_signature");
701 return verify_topic_nonce_proof(cache, public_key, signature.
nonce_proof, secp_context, circuit_cache);
707 return api_impl::derive_public_key(secret, secp_context);
712 return api_impl::verify_signature(*
this, message, signature, secp_context);
715Result<bool> PublicKey::verify_message_nonce_proof(std::span<const unsigned char> message,
719 return api_impl::verify_message_nonce_proof(*
this, message, nonce_proof, secp_context, circuit_cache);
725 return api_impl::verify_message_nonce_proof(cache, *
this, nonce_proof, secp_context, circuit_cache);
728Result<bool> PublicKey::verify_topic_nonce_proof(std::span<const unsigned char> topic,
732 return api_impl::verify_topic_nonce_proof(*
this, topic, nonce_proof, secp_context, circuit_cache);
738 return api_impl::verify_topic_nonce_proof(cache, *
this, nonce_proof, secp_context, circuit_cache);
741Result<bool> PublicKey::verify_message_signature_with_proof(std::span<const unsigned char> message,
745 return api_impl::verify_message_signature_with_proof(*
this, message, signature, secp_context, circuit_cache);
752 return api_impl::verify_message_signature_with_proof(cache, *
this, signature, secp_context, circuit_cache);
755Result<bool> PublicKey::verify_topic_signature_with_proof(std::span<const unsigned char> message,
756 std::span<const unsigned char> topic,
760 return api_impl::verify_topic_signature_with_proof(*
this, message, topic, signature, secp_context, circuit_cache);
764 std::span<const unsigned char> message,
768 return api_impl::verify_topic_signature_with_proof(cache, *
this, message, signature, secp_context, circuit_cache);
772 return api_impl::build_message_proof_cache(message);
776 return api_impl::build_topic_proof_cache(topic);
781 return KeyPair::from_secret(std::move(owned_secret), secp_context);
785 PURIFY_ASSIGN_OR_RETURN(
auto public_key, PublicKey::from_secret(secret, secp_context),
"KeyPair::from_secret:from_secret");
786 return KeyPair(std::move(secret), std::move(public_key));
791 return api_impl::prepare_message_nonce(secret_, message, secp_context);
796 return api_impl::prepare_message_nonce_with_proof(secret_, message, secp_context);
801 return api_impl::prepare_message_nonce_with_proof(secret_, cache, secp_context);
806 return api_impl::prepare_topic_nonce(secret_, topic, secp_context);
811 return api_impl::prepare_topic_nonce_with_proof(secret_, topic, secp_context);
816 return api_impl::prepare_topic_nonce_with_proof(secret_, cache, secp_context);
821 PURIFY_ASSIGN_OR_RETURN(
auto prepared, prepare_message_nonce(message, secp_context),
"KeyPair::sign_message:prepare_message_nonce");
822 return sign_message_with_prepared(message, std::move(prepared), secp_context);
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,
841 PURIFY_ASSIGN_OR_RETURN(
auto prepared, prepare_topic_nonce(topic, secp_context),
"KeyPair::sign_with_topic:prepare_topic_nonce");
842 return sign_with_prepared_topic(message, std::move(prepared), secp_context);
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");
862 return sign_message_with_prepared_proof(message, std::move(prepared), secp_context);
868 "KeyPair::sign_message_with_proof:prepare_message_nonce_with_proof");
869 return sign_message_with_prepared_proof(cache.
message, std::move(prepared), secp_context);
873 std::span<const unsigned char> topic,
876 "KeyPair::sign_with_topic_proof:prepare_topic_nonce_with_proof");
877 return sign_with_prepared_topic_proof(message, std::move(prepared), secp_context);
884 "KeyPair::sign_with_topic_proof:prepare_topic_nonce_with_proof");
885 return sign_with_prepared_topic_proof(message, std::move(prepared), secp_context);
C++ wrappers for the BPPP functionality used by Purify.
Purify result carrier that either holds a value or an error.
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.
Move-only prepared nonce bundled with its public statement proof.
Move-only prepared nonce bound to either a message or a topic.
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.
PreparedNonce::Scope scope
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)
Status validate_proof_cache_circuit(const CircuitLike &circuit, const char *context)
Result< Signature > sign_message_with_prepared(const SecretKey &secret, std::span< const unsigned char > message, PreparedNonce &&prepared, 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.
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.
std::vector< unsigned char > Bytes
Dynamically sized byte string used for messages, serialized witnesses, and proofs.
Result< FieldElement > eval(const SecretKey &secret, const Bytes &message)
Evaluates the Purify PRF for an owned secret key and message.
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)
BigUInt< 4 > UInt256
256-bit unsigned integer used for field elements and curve orders.
Expected< void, Error > Status
Expected-returning convenience alias for Purify status-only APIs.
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.
static BigUInt from_hex(std::string_view hex)
Parses a hexadecimal string with the precondition that the value fits exactly.
Canonical BIP340 keypair derived deterministically from a packed Purify secret.
Cacheable message-bound nonce-proof template.
NativeBulletproofCircuitTemplate circuit_template
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.
Standard 64-byte BIP340 signature.
Cacheable topic-bound nonce-proof template.
NativeBulletproofCircuitTemplate circuit_template
ExperimentalBulletproofBackendCache backend_cache