34 filtered.reserve(hex.size());
36 if (std::isspace(
static_cast<unsigned char>(ch)) == 0) {
37 filtered.push_back(ch);
40 if ((filtered.size() & 1U) != 0) {
43 for (std::size_t i = 0; i < filtered.size(); i += 2) {
44 auto decode = [](
char ch) ->
int {
45 if (ch >=
'0' && ch <=
'9') {
46 return static_cast<int>(ch -
'0');
48 if (ch >=
'a' && ch <=
'f') {
49 return static_cast<int>(10 + ch -
'a');
51 if (ch >=
'A' && ch <=
'F') {
52 return static_cast<int>(10 + ch -
'A');
56 int high = decode(filtered[i]);
57 int low = decode(filtered[i + 1]);
58 if (high < 0 || low < 0) {
61 out.push_back(
static_cast<unsigned char>((high << 4) | low));
72template <std::
size_t N>
78 if (bytes->size() != N) {
81 std::array<unsigned char, N> out{};
82 std::copy(bytes->begin(), bytes->end(), out.begin());
92template <
typename ByteContainer>
94 std::ostringstream out;
95 out << std::hex << std::setfill(
'0');
96 for (
unsigned char byte : bytes) {
97 out << std::setw(2) << static_cast<unsigned>(
byte);
108 std::ofstream file(path, std::ios::binary);
112 file.write(
reinterpret_cast<const char*
>(bytes.data()),
static_cast<std::streamsize
>(bytes.size()));
140 auto print_error = [](
const Error& error) {
141 std::cerr << error.message() <<
"\n";
146 std::cout <<
"Usage: " << argv[0] <<
" gen [<seckey>]: generate a key\n";
147 std::cout <<
" " << argv[0] <<
" eval <seckey> <hexmsg>: evaluate the PRF\n";
148 std::cout <<
" " << argv[0] <<
" verifier <hexmsg> <pubkey>: output verifier circuit for a given message\n";
149 std::cout <<
" " << argv[0] <<
" prove <hexmsg> <seckey>: produce input for verifier\n";
150 std::cout <<
" " << argv[0] <<
" run-circuit <hexmsg> <seckey>: build and evaluate the native verifier circuit\n";
151 std::cout <<
" " << argv[0] <<
" commit-eval <seckey> <hexmsg> <blind32>: commit to the evaluated output\n";
158 std::string command = argv[1];
159 if (command ==
"gen") {
160 std::optional<SecretKey> secret_override;
164 return print_error(parsed.
error());
166 secret_override = std::move(*parsed);
171 return print_error(key.
error());
173 std::cout <<
"z=" << key->secret.packed().to_hex() <<
" # private key\n";
174 std::cout <<
"x=" << key->public_key.to_hex() <<
" # public key\n";
177 if (command ==
"eval") {
184 return print_error(secret.
error());
188 return print_error(message.
error());
192 return print_error(value.
error());
194 std::cout <<
"eval: " << value->to_hex() <<
"\n";
197 if (command ==
"verifier") {
204 return print_error(message.
error());
208 return print_error(pubkey.
error());
212 return print_error(verifier_program.
error());
214 std::cout << *verifier_program <<
"\n";
217 if (command ==
"prove") {
224 return print_error(message.
error());
228 return print_error(secret.
error());
232 return print_error(status.
error());
236 if (command ==
"run-circuit") {
243 return print_error(message.
error());
247 return print_error(secret.
error());
251 return print_error(witness.
error());
255 return print_error(circuit.
error());
257 bool ok = circuit->evaluate(witness->assignment);
258 std::cout <<
"gates=" << circuit->n_gates <<
"\n";
259 std::cout <<
"constraints=" << circuit->c.size() <<
"\n";
260 std::cout <<
"commitments=" << circuit->n_commitments <<
"\n";
261 std::cout << (ok ?
"ok" :
"fail") <<
"\n";
264 if (command ==
"commit-eval") {
270 if (secp_context ==
nullptr) {
275 return print_error(secret.
error());
279 return print_error(message.
error());
283 return print_error(blind.
error());
288 return print_error(committed.
error());
290 std::cout <<
"pubkey=" << committed->public_key.to_hex() <<
"\n";
291 std::cout <<
"output=" << committed->output.to_hex() <<
"\n";
292 std::cout <<
"commit=" <<
hex_from_bytes(committed->commitment) <<
"\n";
295 std::cout <<
"Unknown command\n";
C++ wrappers for the BPPP functionality used by Purify.
Purify result carrier that either holds a value or an error.
bool has_value() const noexcept
Move-only packed Purify secret stored in dedicated heap memory.
static Result< SecretKey > from_hex(std::string_view hex)
Parses and validates a packed Purify secret from hexadecimal text.
Result< CommittedPurifyWitness > commit_output_witness(const Bytes &message, const SecretKey &secret, const ScalarBytes &blind, purify_secp_context *secp_context)
Evaluates Purify, derives its witness, and commits to the output using Purify's default generators.
Status prove(const Bytes &message, const SecretKey &secret, const std::string &output_path="prove.assn")
Writes a serialized witness assignment for a message and secret.
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< BulletproofWitnessData > prove_assignment_data(const Bytes &message, const SecretKey &secret)
Computes the native Purify witness for a message and secret.
int run_cli(int argc, char **argv)
Dispatches the purify_cpp command-line interface.
Result< std::array< unsigned char, N > > array_from_hex(std::string_view hex)
Parses a fixed-size hexadecimal string into an array.
Result< GeneratedKey > generate_key()
Generates a random Purify keypair using the built-in OS RNG.
std::unique_ptr< purify_secp_context, SecpContextDeleter > SecpContextPtr
Result< NativeBulletproofCircuit > verifier_circuit(const Bytes &message, const UInt512 &pubkey)
Builds the native verifier circuit for a message and public key.
SecpContextPtr make_secp_context() noexcept
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.
std::vector< unsigned char > Bytes
Dynamically sized byte string used for messages, serialized witnesses, and proofs.
Result< Bytes > bytes_from_hex(std::string_view hex)
Parses a hexadecimal string into raw bytes.
Status write_file(const std::string &path, const Bytes &bytes)
Writes a byte buffer to disk.
Result< FieldElement > eval(const SecretKey &secret, const Bytes &message)
Evaluates the Purify PRF for an owned secret key and message.
std::string hex_from_bytes(const ByteContainer &bytes)
Encodes a byte container as lowercase hexadecimal.
Umbrella header that re-exports the public Purify API.
static Result< BigUInt > try_from_hex(std::string_view hex)
Parses a hexadecimal string, ignoring optional 0x and whitespace.
Compact error object returned by checked APIs.