30 std::fill(std::begin(generated.public_key), std::end(generated.public_key), 0);
35 std::fill(std::begin(key.xonly_public_key), std::end(key.xonly_public_key), 0);
41 "generated_key_from_core:from_packed");
43 return GeneratedKey{std::move(owned_secret), public_key};
48 out.reserve(prefix.size() + message.size());
49 out.insert(out.end(), prefix.begin(), prefix.end());
50 out.insert(out.end(), message.begin(), message.end());
54void add_expr_slack(NativeBulletproofCircuit::PackedSlackPlan& slack,
const Expr& expr) {
55 for (
const auto& term : expr.linear()) {
56 switch (term.first.kind) {
58 if (term.first.index < slack.wl.size()) {
59 ++slack.wl[term.first.index];
63 if (term.first.index < slack.wr.size()) {
64 ++slack.wr[term.first.index];
68 if (term.first.index < slack.wo.size()) {
69 ++slack.wo[term.first.index];
73 if (term.first.index < slack.wv.size()) {
74 ++slack.wv[term.first.index];
78 assert(
false &&
"verifier_circuit_template should not pack raw witness symbols");
84NativeBulletproofCircuit::PackedSlackPlan build_template_slack(std::size_t n_gates, std::size_t n_commitments,
85 const Expr& p1x,
const Expr& p2x,
const Expr& out) {
86 NativeBulletproofCircuit::PackedSlackPlan slack;
87 slack.constraint_slack = 3;
88 slack.wl.assign(n_gates, 0);
89 slack.wr.assign(n_gates, 0);
90 slack.wo.assign(n_gates, 0);
91 slack.wv.assign(n_commitments, 0);
92 add_expr_slack(slack, p1x.split().second);
93 add_expr_slack(slack, p2x.split().second);
94 add_expr_slack(slack, out);
95 if (!slack.wv.empty()) {
105 "fill_secure_random:purify_fill_secure_random");
116 clear_core_generated_key(generated);
120 clear_core_generated_key(generated);
131 clear_core_generated_key(generated);
135 clear_core_generated_key(generated);
148 std::array<unsigned char, PURIFY_SECRET_KEY_BYTES> secret_bytes = secret.packed().to_bytes_be();
149 std::array<unsigned char, PURIFY_PUBLIC_KEY_BYTES> public_key_bytes{};
153 std::fill(public_key_bytes.begin(), public_key_bytes.end(), 0);
157 std::fill(public_key_bytes.begin(), public_key_bytes.end(), 0);
162 std::array<unsigned char, PURIFY_SECRET_KEY_BYTES> secret_bytes = secret.
packed().
to_bytes_be();
167 clear_core_bip340_key(key);
171 std::copy(std::begin(key.secret_key), std::end(key.secret_key), out.seckey.begin());
172 std::copy(std::begin(key.xonly_public_key), std::end(key.xonly_public_key), out.xonly_pubkey.begin());
173 clear_core_bip340_key(key);
178 std::array<unsigned char, PURIFY_SECRET_KEY_BYTES> secret_bytes = secret.
packed().
to_bytes_be();
179 std::array<unsigned char, PURIFY_FIELD_ELEMENT_BYTES> output_bytes{};
181 purify_eval(output_bytes.data(), secret_bytes.data(), message.data(), message.size());
184 std::fill(output_bytes.begin(), output_bytes.end(), 0);
192 "verifier:hash_to_curve_m1");
194 "verifier:hash_to_curve_m2");
200 "verifier:add_pubkey_and_out");
206 "verifier_circuit:verifier_circuit_template");
207 return template_circuit.instantiate(pubkey);
212 "verifier_circuit_template:hash_to_curve_m1");
214 "verifier_circuit_template:hash_to_curve_m2");
217 "verifier_circuit_template:circuit_main");
220 Expr p1x = result.p1x;
221 Expr p2x = result.p2x;
222 Expr out = result.out;
231 "verifier_circuit_template:pack_with_slack");
239 "prove_assignment_data:hash_to_curve_m1");
241 "prove_assignment_data:hash_to_curve_m2");
243 "prove_assignment_data:mul_secret_affine_p1");
245 "prove_assignment_data:mul_secret_affine_p2");
247 "prove_assignment_data:mul_secret_affine_q1");
249 "prove_assignment_data:mul_secret_affine_q2");
254 "prove_assignment_data:circuit_main");
255 if (transcript.
evaluate(result.p1x) != std::optional<FieldElement>(p1.x)) {
258 if (transcript.
evaluate(result.p2x) != std::optional<FieldElement>(p2.x)) {
261 if (transcript.
evaluate(result.out) != std::optional<FieldElement>(native_out)) {
269 "prove_assignment_data:add_pubkey_and_out");
275 assert(assignment.
has_value() &&
"prove_assignment_data() should materialize a complete assignment");
284 "evaluate_verifier_circuit:verifier_circuit");
290 "evaluate_verifier_circuit:prove_assignment_data");
297 assert(serialized.
has_value() &&
"prove_assignment() should serialize a well-formed assignment");
High-level Purify key generation, evaluation, witness generation, and circuit helpers.
Lowering helper that converts a symbolic transcript into native Bulletproof witness and circuit forms...
bool evaluate(const WitnessAssignments &vars, const FieldElement &commitment) const
Evaluates the lowered symbolic constraints with a concrete commitment value.
std::string to_string() const
Renders the lowered circuit in the legacy textual verifier format.
Status from_transcript(const Transcript &transcript, std::size_t n_bits)
Imports a symbolic transcript and pads it to a power-of-two multiplication count.
void replace_expr_v_with_bp_var(Expr &expr)
Rewrites transcript variable names to their eventual Bulletproof wire aliases.
Status add_pubkey_and_out(const UInt512 &pubkey, Expr p1x, Expr p2x, Expr out)
Binds packed public-key coordinates and the output commitment into explicit constraints.
NativeBulletproofCircuit native_circuit() const
Builds the native sparse circuit object from the lowered assignments and constraints.
Result< BulletproofAssignmentData > assignment_data(const WitnessAssignments &vars) const
Materializes the witness columns expected by the native circuit representation.
Purify result carrier that either holds a value or an error.
bool has_value() const noexcept
Symbolic affine expression over indexed variables and field coefficients.
Field element modulo the backend scalar field used by this implementation.
static Result< FieldElement > try_from_bytes32(const std::array< unsigned char, 32 > &bytes)
Decodes a canonical 32-byte big-endian field element.
static NativeBulletproofCircuitTemplate from_parts(NativeBulletproofCircuit::PackedWithSlack base_packed, Expr p1x, Expr p2x, Expr out)
Builds a template from a lowered base circuit plus late-bound public expressions.
Move-only packed Purify secret stored in dedicated heap memory.
const UInt512 & packed() const noexcept
Exposes the packed secret for lower-level cryptographic operations.
static Result< SecretKey > from_packed(const UInt512 &packed)
Constructs a validated secret key from packed Purify secret bytes.
Result< SecretKey > clone() const
Creates a second owned copy of this secret key.
Checked span wrapper that guarantees a minimum runtime length.
constexpr std::size_t size() const noexcept
constexpr const T * data() const noexcept
Mutable transcript used to record symbolic multiplication, division, and boolean constraints.
std::optional< FieldElement > evaluate(const Expr &expr) const
Evaluates an expression against the transcript's current witness vector.
const WitnessAssignments & varmap() const
Returns the underlying witness assignment vector.
#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.
Bytes tagged_message(std::string_view prefix, const Bytes &message)
constexpr ErrorCode from_core_error_code(purify_error_code code) noexcept
void secure_clear_bytes(void *data, std::size_t size) noexcept
constexpr Unexpected< Error > unexpected_error(ErrorCode code, const char *context=nullptr)
Constructs an unexpected Error value from a machine-readable code.
Result< std::string > verifier(const Bytes &message, const UInt512 &pubkey)
Builds the legacy serialized verifier description for a message and public key.
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< GeneratedKey > generate_key()
Generates a random Purify keypair using the built-in OS RNG.
BigUInt< 8 > UInt512
512-bit unsigned integer used for private and packed public keys.
Result< NativeBulletproofCircuit > verifier_circuit(const Bytes &message, const UInt512 &pubkey)
Builds the native verifier circuit for a message and public key.
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< Bytes > prove_assignment(const Bytes &message, const SecretKey &secret)
Serializes the witness assignment produced for a message and secret.
Result< GeneratedKey > derive_key(const SecretKey &secret)
Derives the packed public key corresponding to a packed secret.
const EllipticCurve & curve1()
Returns the first Purify curve instance.
Result< CircuitMainResult > circuit_main(Transcript &transcript, const JacobianPoint &m1, const JacobianPoint &m2, const std::optional< UInt256 > &z1=std::nullopt, const std::optional< UInt256 > &z2=std::nullopt)
Builds the full symbolic Purify circuit from message points and optional witness scalars.
std::vector< unsigned char > Bytes
Dynamically sized byte string used for messages, serialized witnesses, and proofs.
const JacobianPoint & generator1()
Returns the fixed generator for the first curve.
UInt512 pack_public(const UInt256 &x1, const UInt256 &x2)
Packs two x-coordinates into the reference 512-bit public-key encoding.
Result< FieldElement > eval(const SecretKey &secret, const Bytes &message)
Evaluates the Purify PRF for an owned secret key and message.
Result< bool > evaluate_verifier_circuit(const Bytes &message, const BulletproofWitnessData &witness)
Evaluates the generated verifier circuit against an explicit witness.
Result< std::pair< UInt256, UInt256 > > unpack_secret(const UInt512 &z)
Splits a packed private key into its two per-curve secret scalars.
Result< JacobianPoint > hash_to_curve(const Bytes &data, const EllipticCurve &curve)
Hashes arbitrary data onto the supplied curve by rejection sampling x-coordinates.
Result< UInt512 > random_below(const UInt512 &range, FillRandom &&fill_random)
Samples a uniformly random packed secret below a range using a checked byte-fill source.
const EllipticCurve & curve2()
Returns the second Purify curve instance.
const JacobianPoint & generator2()
Returns the fixed generator for the second curve.
FieldElement combine(const FieldElement &x1, const FieldElement &x2)
Applies the Purify curve-combination map to two x-coordinates.
Expected< void, Error > Status
Expected-returning convenience alias for Purify status-only APIs.
Status fill_secure_random(std::span< unsigned char > bytes) noexcept
Fills a buffer with operating-system randomness.
Public C core for Purify key validation, key derivation, key generation, and evaluation.
purify_error_code purify_generate_key(purify_generated_key *out)
Generates one random Purify keypair.
purify_error_code purify_fill_secure_random(unsigned char *bytes, size_t bytes_len)
Fills a caller-owned buffer with secure operating-system randomness.
purify_error_code
Machine-readable status code returned by the Purify C core.
purify_error_code purify_generate_key_from_seed(purify_generated_key *out, const unsigned char *seed, size_t seed_len)
Deterministically derives one Purify keypair from seed material.
purify_error_code purify_eval(unsigned char out_field_element[PURIFY_FIELD_ELEMENT_BYTES], const unsigned char secret_key[PURIFY_SECRET_KEY_BYTES], const unsigned char *message, size_t message_len)
Evaluates the Purify PRF for one packed secret and message.
purify_error_code purify_derive_public_key(unsigned char out_public_key[PURIFY_PUBLIC_KEY_BYTES], const unsigned char secret_key[PURIFY_SECRET_KEY_BYTES])
Derives the packed public key corresponding to one packed Purify secret.
purify_error_code purify_derive_bip340_key(purify_bip340_key *out, const unsigned char secret_key[PURIFY_SECRET_KEY_BYTES], purify_secp_context *secp_context)
Derives one canonical BIP340 keypair from one packed Purify secret.
static BigUInt from_bytes_be(const unsigned char *data, std::size_t size)
Parses a big-endian byte string into the fixed-width integer.
std::array< unsigned char, Words *8 > to_bytes_be() const
Serializes the value to a fixed-width big-endian byte array.
Canonical BIP340 keypair derived deterministically from a packed Purify secret.
Complete witness bundle for evaluating and proving a Purify instance.
BulletproofAssignmentData assignment
Derived Purify keypair bundle with an owned packed secret and its matching public key.
Native in-memory representation of a Bulletproof-style arithmetic circuit.
Result< PackedWithSlack > pack_with_slack() const
Packs the circuit into one aligned slab with no additional row or constraint slack.
std::size_t n_commitments
Canonical BIP340 keypair derived from one packed Purify secret.
Seed/public-key bundle returned by the C core key-generation entry points.
unsigned char secret_key[PURIFY_SECRET_KEY_BYTES]
unsigned char public_key[PURIFY_PUBLIC_KEY_BYTES]