11#ifndef UFSECP_BUILDING
12#define UFSECP_BUILDING
62#if defined(SECP256K1_BIP324)
69#if defined(SECP256K1_BUILD_ETHEREUM)
100 for (; i <
sizeof(ctx->
last_msg) - 1 && msg[i]; ++i) {
119 std::array<uint8_t, 32> arr;
120 std::memcpy(arr.data(), b, 32);
126 std::array<uint8_t, 32> arr;
127 std::memcpy(arr.data(), b, 32);
133 std::memcpy(out, arr.data(), 32);
140constexpr std::size_t kMuSig2KeyAggHeaderLen = 38;
141constexpr std::size_t kMuSig2KeyAggCoeffLen = 32;
142constexpr std::size_t kMuSig2SessionSerializedLen = 98;
143constexpr std::size_t kMuSig2SessionCountOffset = kMuSig2SessionSerializedLen;
144constexpr std::size_t kMuSig2SessionCountLen = 4;
145constexpr uint32_t kMuSig2MinParticipants = 2;
146constexpr uint32_t kMuSig2MaxKeyAggParticipants =
149static_assert(kMuSig2MaxKeyAggParticipants >= kMuSig2MinParticipants,
150 "MuSig2 keyagg blob must encode at least two participants");
152 "MuSig2 session blob must have room for participant count metadata");
158 std::memcpy(&nk, keyagg, 4);
159 if (nk < kMuSig2MinParticipants || nk > kMuSig2MaxKeyAggParticipants) {
170 std::memcpy(out.
Q_x.data(), qc.data() + 1, 32);
173 for (uint32_t i = 0; i < nk; ++i) {
175 if (!
scalar_parse_strict(keyagg + kMuSig2KeyAggHeaderLen +
static_cast<std::size_t
>(i) * kMuSig2KeyAggCoeffLen,
187 uint32_t& participant_count_out) {
200 std::memcpy(&participant_count_out, session + kMuSig2SessionCountOffset,
sizeof(participant_count_out));
201 if (participant_count_out < kMuSig2MinParticipants || participant_count_out > kMuSig2MaxKeyAggParticipants) {
207static bool checked_mul_size(std::size_t left, std::size_t right, std::size_t& out) {
208 if (left != 0 && right > std::numeric_limits<std::size_t>::max() / left) {
215static bool checked_add_size(std::size_t left, std::size_t right, std::size_t& out) {
216 if (right > std::numeric_limits<std::size_t>::max() - left) {
226static constexpr std::size_t kMaxBatchN = std::size_t{1} << 20;
237#define UFSECP_CATCH_RETURN(ctx_ptr) \
238 catch (const std::bad_alloc&) { \
239 return (ctx_ptr) ? ctx_set_err(ctx_ptr, UFSECP_ERR_INTERNAL, \
240 "allocation failed") \
241 : UFSECP_ERR_INTERNAL; \
243 return (ctx_ptr) ? ctx_set_err(ctx_ptr, UFSECP_ERR_INTERNAL, \
245 : UFSECP_ERR_INTERNAL; \
261 auto a = t.square() * t;
262 auto b = a.square() * t;
263 auto c = b.square().square().square() * b;
264 auto d = c.square().square().square() * b;
265 auto e = d.square().square() * a;
267 for (
int i = 0; i < 11; ++i) f = f.square();
270 for (
int i = 0; i < 22; ++i) g = g.square();
273 for (
int i = 0; i < 44; ++i) h = h.square();
276 for (
int i = 0; i < 88; ++i) j = j.square();
279 for (
int i = 0; i < 44; ++i) k = k.square();
281 auto m = k.square().square().square() * b;
283 for (
int i = 0; i < 23; ++i) y = y.square();
285 for (
int i = 0; i < 6; ++i) y = y.square();
287 y = y.square().square();
292 auto y_bytes = y.to_bytes();
293 bool const y_is_odd = (y_bytes[31] & 1) != 0;
294 bool const want_odd = (pub[0] == 0x03);
295 if (y_is_odd != want_odd) {
304 std::memcpy(out, comp.data(), 33);
315 if (value_ !=
nullptr) {
325 for (
auto& value : values) {
364 default:
return "unknown error";
416 if (!ctx)
return "NULL context";
429 const uint8_t privkey[32]) {
456 const uint8_t tweak[32]) {
467 auto result = sk + tw;
470 if (result.is_zero()) {
480 const uint8_t tweak[32]) {
492 auto result = sk * tw;
495 if (result.is_zero()) {
509 const uint8_t privkey[32],
524 const uint8_t privkey[32],
525 uint8_t pubkey33_out[33]) {
536 const uint8_t privkey[32],
537 uint8_t pubkey65_out[65]) {
544 std::memcpy(pubkey65_out, uncomp.data(), 65);
549 const uint8_t* input,
size_t input_len,
550 uint8_t pubkey33_out[33]) {
554 if (input_len == 33 && (input[0] == 0x02 || input[0] == 0x03)) {
556 if (p.is_infinity()) {
562 if (input_len == 65 && input[0] == 0x04) {
563 std::array<uint8_t, 32> x_bytes, y_bytes;
564 std::memcpy(x_bytes.data(), input + 1, 32);
565 std::memcpy(y_bytes.data(), input + 33, 32);
579 if (p.is_infinity()) {
589 const uint8_t privkey[32],
590 uint8_t xonly32_out[32]) {
601 std::memcpy(xonly32_out, xonly.data(), 32);
610 const uint8_t msg32[32],
611 const uint8_t privkey[32],
612 uint8_t sig64_out[64]) {
616 std::array<uint8_t, 32> msg;
617 std::memcpy(msg.data(), msg32, 32);
626 auto compact = sig.to_compact();
627 std::memcpy(sig64_out, compact.data(), 64);
632 const uint8_t msg32[32],
633 const uint8_t privkey[32],
634 uint8_t sig64_out[64]) {
638 std::array<uint8_t, 32> msg;
639 std::memcpy(msg.data(), msg32, 32);
647 auto compact = sig.to_compact();
648 std::memcpy(sig64_out, compact.data(), 64);
653 const uint8_t msg32[32],
654 const uint8_t sig64[64],
655 const uint8_t pubkey33[33]) {
659 std::array<uint8_t, 32> msg;
660 std::memcpy(msg.data(), msg32, 32);
661 std::array<uint8_t, 64> compact;
662 std::memcpy(compact.data(), sig64, 64);
669 if (pk.is_infinity()) {
681 const uint8_t sig64[64],
682 uint8_t* der_out,
size_t* der_len) {
686 std::array<uint8_t, 64> compact;
687 std::memcpy(compact.data(), sig64, 64);
694 auto [der, actual_len] = ecdsasig.
to_der();
695 if (*der_len < actual_len) {
699 std::memcpy(der_out, der.data(), actual_len);
700 *der_len = actual_len;
705 const uint8_t* der,
size_t der_len,
706 uint8_t sig64_out[64]) {
722 if (der_len < 8 || der_len > 72 || der[0] != 0x30) {
731 size_t const seq_len = der[1];
732 if (seq_len + 2 != der_len) {
739 auto parse_int = [&](
const char* name,
const uint8_t*& out_ptr,
741 if (pos >= der_len || der[pos] != 0x02) {
745 if (pos >= der_len) {
749 if (der[pos] & 0x80) {
752 size_t const int_len = der[pos++];
753 if (int_len == 0 || pos + int_len > der_len) {
757 if (der[pos] & 0x80) {
763 if (int_len > 1 && der[pos] == 0x00 && !(der[pos + 1] & 0x80)) {
770 if (out_len > 0 && out_ptr[0] == 0x00) { out_ptr++; out_len--; }
777 const uint8_t* r_ptr =
nullptr;
778 size_t r_data_len = 0;
780 auto rc = parse_int(
"R", r_ptr, r_data_len);
785 const uint8_t* s_ptr =
nullptr;
786 size_t s_data_len = 0;
788 auto rc = parse_int(
"S", s_ptr, s_data_len);
793 if (pos != der_len) {
797 if (r_data_len > 32 || s_data_len > 32) {
802 std::memset(sig64_out, 0, 64);
805 if (r_data_len > 0 && r_ptr) {
806 std::memcpy(sig64_out + (32 - r_data_len), r_ptr, r_data_len);
808 if (s_data_len > 0 && s_ptr) {
809 std::memcpy(sig64_out + 32 + (32 - s_data_len), s_ptr, s_data_len);
825 const uint8_t msg32[32],
826 const uint8_t privkey[32],
827 uint8_t sig64_out[64],
829 if (!ctx || !msg32 || !privkey || !sig64_out || !recid_out) {
834 std::array<uint8_t, 32> msg;
835 std::memcpy(msg.data(), msg32, 32);
849 auto normalized = rsig.sig.normalize();
850 auto compact = normalized.to_compact();
851 std::memcpy(sig64_out, compact.data(), 64);
852 *recid_out = rsig.recid;
857 const uint8_t msg32[32],
858 const uint8_t sig64[64],
860 uint8_t pubkey33_out[33]) {
864 if (recid < 0 || recid > 3) {
868 std::array<uint8_t, 32> msg;
869 std::memcpy(msg.data(), msg32, 32);
870 std::array<uint8_t, 64> compact;
871 std::memcpy(compact.data(), sig64, 64);
892 const uint8_t msg32[32],
893 const uint8_t privkey[32],
894 const uint8_t aux_rand[32],
895 uint8_t sig64_out[64]) {
896 if (!ctx || !msg32 || !privkey || !aux_rand || !sig64_out) {
906 std::array<uint8_t, 32> msg_arr, aux_arr;
907 std::memcpy(msg_arr.data(), msg32, 32);
908 std::memcpy(aux_arr.data(), aux_rand, 32);
914 auto bytes = sig.to_bytes();
915 std::memcpy(sig64_out, bytes.data(), 64);
920 const uint8_t msg32[32],
921 const uint8_t privkey[32],
922 const uint8_t aux_rand[32],
923 uint8_t sig64_out[64]) {
924 if (!ctx || !msg32 || !privkey || !aux_rand || !sig64_out) {
934 std::array<uint8_t, 32> msg_arr, aux_arr;
935 std::memcpy(msg_arr.data(), msg32, 32);
936 std::memcpy(aux_arr.data(), aux_rand, 32);
942 auto bytes = sig.to_bytes();
943 std::memcpy(sig64_out, bytes.data(), 64);
950 const uint8_t* msgs32,
951 const uint8_t* privkeys32,
957 std::size_t total_msg_bytes, total_sig_bytes;
958 if (!checked_mul_size(count, std::size_t{32}, total_msg_bytes)
959 || !checked_mul_size(count, std::size_t{64}, total_sig_bytes))
961 for (
size_t i = 0; i < count; ++i) {
962 std::array<uint8_t, 32> msg;
963 std::memcpy(msg.data(), msgs32 + i * 32, 32);
968 "privkey[i] is zero or >= n");
972 auto compact = sig.to_compact();
973 std::memcpy(sigs64_out + i * 64, compact.data(), 64);
981 const uint8_t* msgs32,
982 const uint8_t* privkeys32,
983 const uint8_t* aux_rands32,
989 std::size_t total_msg_bytes, total_sig_bytes;
990 if (!checked_mul_size(count, std::size_t{32}, total_msg_bytes)
991 || !checked_mul_size(count, std::size_t{64}, total_sig_bytes))
994 static constexpr uint8_t kZeroAux[32] = {};
996 for (
size_t i = 0; i < count; ++i) {
1001 "privkey[i] is zero or >= n");
1004 std::array<uint8_t, 32> msg_arr, aux_arr;
1005 std::memcpy(msg_arr.data(), msgs32 + i * 32, 32);
1006 const uint8_t* aux_src = aux_rands32 ? aux_rands32 + i * 32 : kZeroAux;
1007 std::memcpy(aux_arr.data(), aux_src, 32);
1014 auto sig_bytes = sig.to_bytes();
1015 std::memcpy(sigs64_out + i * 64, sig_bytes.data(), 64);
1021 const uint8_t msg32[32],
1022 const uint8_t sig64[64],
1023 const uint8_t pubkey_x[32]) {
1039 std::array<uint8_t, 32> pk_arr, msg_arr;
1040 std::memcpy(pk_arr.data(), pubkey_x, 32);
1041 std::memcpy(msg_arr.data(), msg32, 32);
1055 const uint8_t privkey[32],
1056 const uint8_t pubkey33[33],
1070 const uint8_t privkey[32],
1071 const uint8_t pubkey33[33],
1072 uint8_t secret32_out[32]) {
1080 std::memcpy(secret32_out, secret.data(), 32);
1086 const uint8_t privkey[32],
1087 const uint8_t pubkey33[33],
1088 uint8_t secret32_out[32]) {
1096 std::memcpy(secret32_out, secret.data(), 32);
1102 const uint8_t privkey[32],
1103 const uint8_t pubkey33[33],
1104 uint8_t secret32_out[32]) {
1112 std::memcpy(secret32_out, secret.data(), 32);
1122 uint8_t digest32_out[32]) {
1125 hasher.
update(data, len);
1127 std::memcpy(digest32_out, digest.data(), 32);
1132 uint8_t digest20_out[20]) {
1135 std::memcpy(digest20_out, h.data(), 20);
1140 const uint8_t* data,
size_t len,
1141 uint8_t digest32_out[32]) {
1144 std::memcpy(digest32_out, h.data(), 32);
1153 const uint8_t pubkey33[33],
int network,
1154 char* addr_out,
size_t* addr_len) {
1159 if (pk.is_infinity()) {
1167 if (*addr_len < addr.size() + 1) {
1170 std::memcpy(addr_out, addr.c_str(), addr.size() + 1);
1171 *addr_len = addr.size();
1177 const uint8_t pubkey33[33],
int network,
1178 char* addr_out,
size_t* addr_len) {
1183 if (pk.is_infinity()) {
1191 if (*addr_len < addr.size() + 1) {
1194 std::memcpy(addr_out, addr.c_str(), addr.size() + 1);
1195 *addr_len = addr.size();
1201 const uint8_t internal_key_x[32],
int network,
1202 char* addr_out,
size_t* addr_len) {
1209 for (
int i = 0; i < 32; ++i) acc |= internal_key_x[i];
1213 std::array<uint8_t, 32> key_x;
1214 std::memcpy(key_x.data(), internal_key_x, 32);
1220 if (*addr_len < addr.size() + 1) {
1223 std::memcpy(addr_out, addr.c_str(), addr.size() + 1);
1224 *addr_len = addr.size();
1230 const uint8_t* redeem_script,
size_t redeem_script_len,
1232 char* addr_out,
size_t* addr_len) {
1244 std::memcpy(addr_out, addr.c_str(), addr.size() + 1);
1245 *addr_len = addr.size();
1252 const uint8_t pubkey33[33],
1254 char* addr_out,
size_t* addr_len) {
1259 if (pk.is_infinity()) {
1267 if (*addr_len < addr.size() + 1) {
1270 std::memcpy(addr_out, addr.c_str(), addr.size() + 1);
1271 *addr_len = addr.size();
1281 const uint8_t privkey[32],
1282 int compressed,
int network,
1283 char* wif_out,
size_t* wif_len) {
1297 if (*wif_len < wif.size() + 1) {
1300 std::memcpy(wif_out, wif.c_str(), wif.size() + 1);
1301 *wif_len = wif.size();
1308 uint8_t privkey32_out[32],
1309 int* compressed_out,
1311 if (!ctx || !wif || !privkey32_out || !compressed_out || !network_out) {
1318 if (!result.valid) {
1324 *compressed_out = result.compressed ? 1 : 0;
1337 std::memcpy(out->
data, serialized.data(), 78);
1339 std::memset(out->
_pad, 0,
sizeof(out->
_pad));
1345 std::memcpy(ek.parent_fingerprint.data(), k->
data + 5, 4);
1346 ek.child_number = (uint32_t(k->
data[9]) << 24) | (uint32_t(k->
data[10]) << 16) |
1347 (uint32_t(k->
data[11]) << 8) | uint32_t(k->
data[12]);
1348 std::memcpy(ek.chain_code.data(), k->
data + 13, 32);
1349 std::memcpy(ek.key.data(), k->
data + 46, 32);
1351 ek.is_private =
true;
1353 ek.is_private =
false;
1354 ek.pub_prefix = k->
data[45];
1365 if (key->
_pad[0] != 0 || key->
_pad[1] != 0 || key->
_pad[2] != 0) {
1369 const uint32_t version = (uint32_t(key->
data[0]) << 24) |
1370 (uint32_t(key->
data[1]) << 16) |
1371 (uint32_t(key->
data[2]) << 8) |
1372 uint32_t(key->
data[3]);
1373 const uint32_t expected_version = key->
is_private ? 0x0488ADE4u : 0x0488B21Eu;
1374 if (version != expected_version) {
1379 if (key->
data[45] != 0x00) {
1388 if (key->
data[45] != 0x02 && key->
data[45] != 0x03) {
1392 if (pk.is_infinity()) {
1402 const uint8_t* seed,
size_t seed_len,
1407 if (seed_len < 16 || seed_len > 64) {
1434 auto [child, ok] = ek.derive_child(index);
1476 uint8_t privkey32_out[32]) {
1489 auto sk = ek.private_key();
1499 uint8_t pubkey33_out[33]) {
1508 auto pk = ek.public_key();
1509 if (pk.is_infinity()) {
1525 const uint8_t internal_x[32],
1526 const uint8_t* merkle_root,
1527 uint8_t output_x_out[32],
1529 if (!ctx || !internal_x || !output_x_out || !parity_out) {
1537 for (
int i = 0; i < 32; ++i) acc |= internal_x[i];
1541 std::array<uint8_t, 32> ik;
1542 std::memcpy(ik.data(), internal_x, 32);
1543 size_t const mr_len = merkle_root ? 32 : 0;
1546 std::memcpy(output_x_out, ok_x.data(), 32);
1547 *parity_out = parity;
1552 const uint8_t privkey[32],
1553 const uint8_t* merkle_root,
1554 uint8_t tweaked32_out[32]) {
1562 size_t const mr_len = merkle_root ? 32 : 0;
1566 if (tweaked.is_zero()) {
1577 const uint8_t output_x[32],
int output_parity,
1578 const uint8_t internal_x[32],
1579 const uint8_t* merkle_root,
size_t merkle_root_len) {
1584 std::array<uint8_t, 32> ok_x, ik_x;
1585 std::memcpy(ok_x.data(), output_x, 32);
1586 std::memcpy(ik_x.data(), internal_x, 32);
1589 merkle_root, merkle_root_len)) {
1603 const uint8_t hash_prevouts[32],
1604 const uint8_t hash_sequence[32],
1605 const uint8_t outpoint_txid[32], uint32_t outpoint_vout,
1606 const uint8_t* script_code,
size_t script_code_len,
1609 const uint8_t hash_outputs[32],
1611 uint32_t sighash_type,
1612 uint8_t sighash_out[32]) {
1613 if (!ctx || !hash_prevouts || !hash_sequence || !outpoint_txid ||
1614 !script_code || !hash_outputs || !sighash_out)
1620 std::memcpy(pre.hash_prevouts.data(), hash_prevouts, 32);
1621 std::memcpy(pre.hash_sequence.data(), hash_sequence, 32);
1622 std::memcpy(pre.hash_outputs.data(), hash_outputs, 32);
1623 pre.locktime = locktime;
1626 std::memcpy(op.txid.data(), outpoint_txid, 32);
1627 op.vout = outpoint_vout;
1630 value, sequence, sighash_type);
1631 std::memcpy(sighash_out, h.data(), 32);
1636 const uint8_t pubkey_hash[20],
1637 uint8_t script_code_out[25]) {
1641 std::memcpy(script_code_out, sc.data(), 25);
1651 size_t& offset, uint64_t& val) {
1652 if (offset >= len)
return 0;
1653 uint8_t first = buf[offset++];
1654 if (first < 0xFD) { val = first;
return 1; }
1655 if (first == 0xFD) {
1656 if (offset + 2 > len)
return 0;
1657 val = uint64_t(buf[offset]) | (uint64_t(buf[offset+1]) << 8);
1658 offset += 2;
return 3;
1660 if (first == 0xFE) {
1661 if (offset + 4 > len)
return 0;
1662 val = uint64_t(buf[offset]) | (uint64_t(buf[offset+1]) << 8) |
1663 (uint64_t(buf[offset+2]) << 16) | (uint64_t(buf[offset+3]) << 24);
1664 offset += 4;
return 5;
1667 if (offset + 8 > len)
return 0;
1669 for (
int i = 0; i < 8; ++i) val |= uint64_t(buf[offset+i]) << (8*i);
1670 offset += 8;
return 9;
1677 if (offset + sz > len)
return false;
1678 offset +=
static_cast<size_t>(sz);
1684 const uint8_t* raw_tx,
size_t raw_tx_len,
1685 uint8_t txid_out[32]) {
1690 bool has_witness = (raw_tx_len > 6 && raw_tx[4] == 0x00 && raw_tx[5] == 0x01);
1695 std::memcpy(txid_out, h.data(), 32);
1708 size_t cs_start = off;
1712 size_t io_start = cs_start;
1715 for (uint64_t i = 0; i < n_in; ++i) {
1728 for (uint64_t i = 0; i < n_out; ++i) {
1733 size_t io_end = off;
1736 h1.
update(raw_tx + io_start, io_end - io_start);
1740 h1.
update(raw_tx + raw_tx_len - 4, 4);
1744 h2.
update(first.data(), 32);
1746 std::memcpy(txid_out, txid.data(), 32);
1752 const uint8_t* raw_tx,
size_t raw_tx_len,
1753 uint8_t wtxid_out[32]) {
1759 std::memcpy(wtxid_out, h.data(), 32);
1764 const uint8_t witness_root[32],
1765 const uint8_t witness_nonce[32],
1766 uint8_t commitment_out[32]) {
1767 if (!witness_root || !witness_nonce || !commitment_out)
1770 std::array<uint8_t, 32> wr, wn;
1771 std::memcpy(wr.data(), witness_root, 32);
1772 std::memcpy(wn.data(), witness_nonce, 32);
1775 std::memcpy(commitment_out, c.data(), 32);
1784 const uint8_t* script,
size_t script_len) {
1785 if (!script)
return 0;
1790 const uint8_t* script,
size_t script_len,
1792 uint8_t* program_out,
size_t* program_len_out) {
1793 if (!script || !version_out || !program_out || !program_len_out)
1797 if (wp.version < 0) {
1799 *program_len_out = 0;
1803 *version_out = wp.version;
1804 *program_len_out = wp.program.size();
1805 std::memcpy(program_out, wp.program.data(), wp.program.size());
1810 const uint8_t pubkey_hash[20],
1811 uint8_t spk_out[22]) {
1815 std::memcpy(spk_out, spk.data(), 22);
1820 const uint8_t script_hash[32],
1821 uint8_t spk_out[34]) {
1825 std::memcpy(spk_out, spk.data(), 34);
1830 const uint8_t output_key[32],
1831 uint8_t spk_out[34]) {
1835 std::memcpy(spk_out, spk.data(), 34);
1840 const uint8_t* script,
size_t script_len,
1841 uint8_t hash_out[32]) {
1846 std::memcpy(hash_out, h.data(), 32);
1857 uint32_t version, uint32_t locktime,
1859 const uint8_t* prevout_txids_flat,
1860 const uint32_t* prevout_vouts,
1861 const uint64_t* input_amounts,
1862 const uint32_t* input_sequences,
1863 const uint8_t*
const* input_spks,
1864 const size_t* input_spk_lens,
1865 size_t output_count,
1866 const uint64_t* output_values,
1867 const uint8_t*
const* output_spks,
1868 const size_t* output_spk_lens,
1869 std::vector<std::array<uint8_t, 32>>& txid_storage) {
1872 txid_storage.resize(input_count);
1873 for (
size_t i = 0; i < input_count; ++i) {
1874 std::memcpy(txid_storage[i].data(), prevout_txids_flat + i * 32, 32);
1879 td.locktime = locktime;
1880 td.input_count = input_count;
1881 td.prevout_txids = txid_storage.data();
1882 td.prevout_vouts = prevout_vouts;
1883 td.input_amounts = input_amounts;
1884 td.input_sequences = input_sequences;
1885 td.input_scriptpubkeys = input_spks;
1886 td.input_scriptpubkey_lens = input_spk_lens;
1887 td.output_count = output_count;
1888 td.output_values = output_values;
1889 td.output_scriptpubkeys = output_spks;
1890 td.output_scriptpubkey_lens = output_spk_lens;
1896 uint32_t version, uint32_t locktime,
1898 const uint8_t* prevout_txids,
1899 const uint32_t* prevout_vouts,
1900 const uint64_t* input_amounts,
1901 const uint32_t* input_sequences,
1902 const uint8_t*
const* input_spks,
1903 const size_t* input_spk_lens,
1904 size_t output_count,
1905 const uint64_t* output_values,
1906 const uint8_t*
const* output_spks,
1907 const size_t* output_spk_lens,
1910 const uint8_t* annex,
size_t annex_len,
1911 uint8_t sighash_out[32]) {
1912 if (!ctx || !prevout_txids || !prevout_vouts || !input_amounts ||
1913 !input_sequences || !input_spks || !input_spk_lens ||
1914 !output_values || !output_spks || !output_spk_lens || !sighash_out)
1916 if (input_index >= input_count)
1921 std::vector<std::array<uint8_t, 32>> txid_storage;
1923 prevout_txids, prevout_vouts, input_amounts, input_sequences,
1924 input_spks, input_spk_lens, output_count, output_values,
1925 output_spks, output_spk_lens, txid_storage);
1929 std::memcpy(sighash_out, h.data(), 32);
1936 uint32_t version, uint32_t locktime,
1938 const uint8_t* prevout_txids,
1939 const uint32_t* prevout_vouts,
1940 const uint64_t* input_amounts,
1941 const uint32_t* input_sequences,
1942 const uint8_t*
const* input_spks,
1943 const size_t* input_spk_lens,
1944 size_t output_count,
1945 const uint64_t* output_values,
1946 const uint8_t*
const* output_spks,
1947 const size_t* output_spk_lens,
1950 const uint8_t tapleaf_hash[32],
1951 uint8_t key_version,
1952 uint32_t code_separator_pos,
1953 const uint8_t* annex,
size_t annex_len,
1954 uint8_t sighash_out[32]) {
1955 if (!ctx || !prevout_txids || !prevout_vouts || !input_amounts ||
1956 !input_sequences || !input_spks || !input_spk_lens ||
1957 !output_values || !output_spks || !output_spk_lens ||
1958 !tapleaf_hash || !sighash_out)
1960 if (input_index >= input_count)
1965 std::vector<std::array<uint8_t, 32>> txid_storage;
1967 prevout_txids, prevout_vouts, input_amounts, input_sequences,
1968 input_spks, input_spk_lens, output_count, output_values,
1969 output_spks, output_spk_lens, txid_storage);
1971 std::array<uint8_t, 32> tlh;
1972 std::memcpy(tlh.data(), tapleaf_hash, 32);
1975 tlh, key_version, code_separator_pos,
1977 std::memcpy(sighash_out, h.data(), 32);
1987 const uint8_t a33[33],
1988 const uint8_t b33[33],
1989 uint8_t out33[33]) {
1993 if (pa.is_infinity()) {
1997 if (pb.is_infinity()) {
2000 auto sum = pa.add(pb);
2001 if (sum.is_infinity()) {
2009 const uint8_t pubkey33[33],
2010 uint8_t out33[33]) {
2014 if (p.is_infinity()) {
2017 auto neg = p.negate();
2023 const uint8_t pubkey33[33],
2024 const uint8_t tweak[32],
2025 uint8_t out33[33]) {
2029 if (p.is_infinity()) {
2037 auto result = p.
add(tG);
2038 if (result.is_infinity()) {
2046 const uint8_t pubkey33[33],
2047 const uint8_t tweak[32],
2048 uint8_t out33[33]) {
2052 if (p.is_infinity()) {
2059 auto result = p.scalar_mul(tw);
2060 if (result.is_infinity()) {
2068 const uint8_t* pubkeys,
2070 uint8_t out33[33]) {
2074 std::size_t total_pubkey_bytes = 0;
2075 if (!checked_mul_size(n,
static_cast<std::size_t
>(33), total_pubkey_bytes)) {
2079 if (acc.is_infinity()) {
2082 for (
size_t i = 1; i < n; ++i) {
2084 if (pi.is_infinity()) {
2089 if (acc.is_infinity()) {
2101 size_t entropy_bytes,
2102 const uint8_t* entropy_in,
2104 size_t* mnemonic_len) {
2107 if (entropy_bytes != 16 && entropy_bytes != 20 && entropy_bytes != 24 &&
2108 entropy_bytes != 28 && entropy_bytes != 32) {
2116 if (*mnemonic_len < mnemonic.size() + 1) {
2119 std::memcpy(mnemonic_out, mnemonic.c_str(), mnemonic.size() + 1);
2120 *mnemonic_len = mnemonic.size();
2126 const char* mnemonic) {
2137 const char* mnemonic,
2138 const char* passphrase,
2139 uint8_t seed64_out[64]) {
2143 const std::string pass = passphrase ? passphrase :
"";
2148 std::memcpy(seed64_out, seed.data(), 64);
2155 const char* mnemonic,
2156 uint8_t* entropy_out,
2157 size_t* entropy_len) {
2165 if (*entropy_len < ent.length) {
2168 std::memcpy(entropy_out, ent.data.data(), ent.length);
2169 *entropy_len = ent.length;
2179 const uint8_t* entries,
size_t n) {
2184 std::size_t total_bytes = 0;
2185 if (!checked_mul_size(n, std::size_t{128}, total_bytes))
2189 std::vector<secp256k1::SchnorrBatchEntry> batch(n);
2190 for (
size_t i = 0; i < n; ++i) {
2191 const uint8_t* e = entries + i * 128;
2197 std::memcpy(batch[i].pubkey_x.data(), e, 32);
2198 std::memcpy(batch[i].message.data(), e + 32, 32);
2211 const uint8_t* entries,
size_t n) {
2216 std::size_t total_bytes = 0;
2217 if (!checked_mul_size(n, std::size_t{129}, total_bytes))
2221 std::vector<secp256k1::ECDSABatchEntry> batch(n);
2222 for (
size_t i = 0; i < n; ++i) {
2223 const uint8_t* e = entries + i * 129;
2224 std::memcpy(batch[i].msg_hash.data(), e, 32);
2226 if (batch[i].public_key.is_infinity()) {
2229 std::array<uint8_t, 64> compact;
2230 std::memcpy(compact.data(), e + 65, 64);
2243 ufsecp_ctx* ctx,
const uint8_t* entries,
size_t n,
2244 size_t* invalid_out,
size_t* invalid_count) {
2249 std::vector<secp256k1::SchnorrBatchEntry> batch(n);
2250 for (
size_t i = 0; i < n; ++i) {
2251 const uint8_t* e = entries + i * 128;
2256 std::memcpy(batch[i].pubkey_x.data(), e, 32);
2257 std::memcpy(batch[i].message.data(), e + 32, 32);
2263 size_t const capacity = *invalid_count;
2264 size_t const count = invalids.size() < capacity ? invalids.size() : capacity;
2265 *invalid_count = invalids.size();
2266 for (
size_t i = 0; i < count; ++i) {
2267 invalid_out[i] = invalids[i];
2274 ufsecp_ctx* ctx,
const uint8_t* entries,
size_t n,
2275 size_t* invalid_out,
size_t* invalid_count) {
2280 std::vector<secp256k1::ECDSABatchEntry> batch(n);
2281 for (
size_t i = 0; i < n; ++i) {
2282 const uint8_t* e = entries + i * 129;
2283 std::memcpy(batch[i].msg_hash.data(), e, 32);
2285 if (batch[i].public_key.is_infinity()) {
2288 std::array<uint8_t, 64> compact;
2289 std::memcpy(compact.data(), e + 65, 64);
2295 size_t const capacity = *invalid_count;
2296 size_t const count = invalids.size() < capacity ? invalids.size() : capacity;
2297 *invalid_count = invalids.size();
2298 for (
size_t i = 0; i < count; ++i) {
2299 invalid_out[i] = invalids[i];
2310 uint8_t digest64_out[64]) {
2313 std::memcpy(digest64_out, hash.data(), 64);
2322 const uint8_t a[32],
const uint8_t P33[33],
2323 const uint8_t b[32],
const uint8_t Q33[33],
2324 uint8_t out33[33]) {
2335 if (P.is_infinity()) {
2339 if (Q.is_infinity()) {
2343 if (result.is_infinity()) {
2351 const uint8_t* scalars,
2352 const uint8_t* points,
2354 uint8_t out33[33]) {
2359 std::size_t total_scalar_bytes = 0;
2360 std::size_t total_point_bytes = 0;
2361 if (!checked_mul_size(n,
static_cast<std::size_t
>(32), total_scalar_bytes)
2362 || !checked_mul_size(n,
static_cast<std::size_t
>(33), total_point_bytes)) {
2366 std::vector<Scalar> svec(n);
2367 std::vector<Point> pvec(n);
2368 for (
size_t i = 0; i < n; ++i) {
2373 if (pvec[i].is_infinity()) {
2378 if (result.is_infinity()) {
2391 const uint8_t* pubkeys,
size_t n,
2393 uint8_t agg_pubkey32_out[32]) {
2396 std::memset(agg_pubkey32_out, 0, 32);
2398 if (n > kMuSig2MaxKeyAggParticipants) {
2403 std::vector<std::array<uint8_t, 32>> pks(n);
2404 for (
size_t i = 0; i < n; ++i) {
2405 std::memcpy(pks[i].data(), pubkeys + i * 32, 32);
2408 std::memcpy(agg_pubkey32_out, kagg.Q_x.data(), 32);
2411 const auto nk =
static_cast<uint32_t
>(kagg.key_coefficients.size());
2412 std::memcpy(keyagg_out, &nk, 4);
2413 keyagg_out[4] = kagg.Q_negated ? 1 : 0;
2416 scalar_to_bytes(kagg.key_coefficients[i], keyagg_out + 38 +
static_cast<size_t>(i) * 32);
2423 const uint8_t privkey[32],
2424 const uint8_t pubkey32[32],
2425 const uint8_t agg_pubkey32[32],
2426 const uint8_t msg32[32],
2427 const uint8_t extra_in[32],
2430 if (!ctx || !privkey || !pubkey32 || !agg_pubkey32 || !msg32 ||
2437 std::array<uint8_t, 32> pk_arr, agg_arr, msg_arr;
2438 std::memcpy(pk_arr.data(), pubkey32, 32);
2439 std::memcpy(agg_arr.data(), agg_pubkey32, 32);
2440 std::memcpy(msg_arr.data(), msg32, 32);
2444 auto k1_bytes = sec.k1.to_bytes();
2445 auto k2_bytes = sec.k2.to_bytes();
2446 std::memcpy(secnonce_out, k1_bytes.data(), 32);
2447 std::memcpy(secnonce_out + 32, k2_bytes.data(), 32);
2451 auto pn = pub.serialize();
2452 std::memcpy(pubnonce_out, pn.data(), 66);
2458 const uint8_t* pubnonces,
size_t n,
2465 std::size_t total_bytes = 0;
2466 if (!checked_mul_size(n, std::size_t{66}, total_bytes))
2469 std::vector<secp256k1::MuSig2PubNonce> pns(n);
2470 for (
size_t i = 0; i < n; ++i) {
2477 std::array<uint8_t, 66> buf;
2478 std::memcpy(buf.data(), pubnonces + i * 66, 66);
2483 auto r1 = agg.R1.to_compressed();
2484 auto r2 = agg.R2.to_compressed();
2485 std::memcpy(aggnonce_out, r1.data(), 33);
2486 std::memcpy(aggnonce_out + 33, r2.data(), 33);
2495 const uint8_t msg32[32],
2513 const ufsecp_error_t rc = parse_musig2_keyagg(ctx, keyagg, kagg);
2518 std::array<uint8_t, 32> msg_arr;
2519 std::memcpy(msg_arr.data(), msg32, 32);
2526 session_out[97] = sess.R_negated ? 1 : 0;
2527 const uint32_t participant_count =
static_cast<uint32_t
>(kagg.
key_coefficients.size());
2528 std::memcpy(session_out + kMuSig2SessionCountOffset, &participant_count,
sizeof(participant_count));
2535 const uint8_t privkey[32],
2538 size_t signer_index,
2539 uint8_t partial_sig32_out[32]) {
2540 if (!ctx || !secnonce || !privkey || !keyagg || !session || !partial_sig32_out) {
2560 const ufsecp_error_t rc = parse_musig2_keyagg(ctx, keyagg, kagg);
2569 uint32_t session_participant_count = 0;
2571 const ufsecp_error_t rc = parse_musig2_session(ctx, session, sess, session_participant_count);
2590 const uint8_t partial_sig32[32],
2592 const uint8_t pubkey32[32],
2595 size_t signer_index) {
2596 if (!ctx || !partial_sig32 || !pubnonce || !pubkey32 || !keyagg || !session) {
2604 std::array<uint8_t, 66> pn_buf;
2605 std::memcpy(pn_buf.data(), pubnonce, 66);
2607 std::array<uint8_t, 32> pk_arr;
2608 std::memcpy(pk_arr.data(), pubkey32, 32);
2611 const ufsecp_error_t rc = parse_musig2_keyagg(ctx, keyagg, kagg);
2620 uint32_t session_participant_count = 0;
2622 const ufsecp_error_t rc = parse_musig2_session(ctx, session, sess, session_participant_count);
2638 const uint8_t* partial_sigs,
size_t n,
2640 uint8_t sig64_out[64]) {
2647 std::size_t total_bytes = 0;
2648 if (!checked_mul_size(n, std::size_t{32}, total_bytes))
2651 std::vector<Scalar> psigs(n);
2652 for (
size_t i = 0; i < n; ++i) {
2658 uint32_t session_participant_count = 0;
2660 const ufsecp_error_t rc = parse_musig2_session(ctx, session, sess, session_participant_count);
2665 if (n != session_participant_count) {
2669 std::memcpy(sig64_out, final_sig.data(), 64);
2680 uint32_t participant_id, uint32_t threshold, uint32_t num_participants,
2681 const uint8_t seed[32],
2682 uint8_t* commits_out,
size_t* commits_len,
2683 uint8_t* shares_out,
size_t* shares_len) {
2684 if (!ctx || !seed || !commits_out || !commits_len || !shares_out || !shares_len) {
2688 if (threshold < 2 || threshold > num_participants) {
2691 if (participant_id == 0 || participant_id > num_participants) {
2694 if (num_participants > kMaxBatchN) {
2698 std::size_t required_commit_coeff_bytes = 0;
2699 std::size_t required_commits = 0;
2700 std::size_t required_shares = 0;
2701 if (!checked_mul_size(
static_cast<std::size_t
>(threshold),
static_cast<std::size_t
>(33), required_commit_coeff_bytes)
2702 || !checked_add_size(
static_cast<std::size_t
>(8), required_commit_coeff_bytes, required_commits)
2703 || !checked_mul_size(
static_cast<std::size_t
>(num_participants),
static_cast<std::size_t
>(
UFSECP_FROST_SHARE_LEN), required_shares)) {
2706 if (*commits_len < required_commits) {
2709 if (*shares_len < required_shares) {
2712 std::array<uint8_t, 32> seed_arr;
2713 std::memcpy(seed_arr.data(), seed, 32);
2715 participant_id, threshold, num_participants, seed_arr);
2717 auto erase_shares = [&]() {
2718 for (
auto& share : shares) {
2723 const size_t coeff_count = commit.coeffs.size();
2724 const size_t needed_commits = 8 + coeff_count * 33;
2725 if (*commits_len < needed_commits) {
2729 const auto cc32 =
static_cast<uint32_t
>(coeff_count);
2730 std::memcpy(commits_out, &cc32, 4);
2731 std::memcpy(commits_out + 4, &commit.from, 4);
2732 for (
size_t i = 0; i < coeff_count; ++i) {
2736 *commits_len = 8 + coeff_count * 33;
2739 if (*shares_len < needed_shares) {
2743 for (
size_t i = 0; i < shares.size(); ++i) {
2745 std::memcpy(s, &shares[i].from, 4);
2748 *shares_len = needed_shares;
2756 uint32_t participant_id,
2757 const uint8_t* all_commits,
size_t commits_len,
2758 const uint8_t* received_shares,
size_t shares_len,
2759 uint32_t threshold, uint32_t num_participants,
2763 if (threshold < 2 || threshold > num_participants) {
2766 if (participant_id == 0 || participant_id > num_participants) {
2769 if (num_participants > kMaxBatchN) {
2773 std::size_t expected_commit_coeff_bytes = 0;
2774 std::size_t expected_commit_record_len = 0;
2775 std::size_t expected_commits_len = 0;
2776 std::size_t expected_shares_len = 0;
2777 if (!checked_mul_size(
static_cast<std::size_t
>(threshold),
static_cast<std::size_t
>(33), expected_commit_coeff_bytes)
2778 || !checked_add_size(
static_cast<std::size_t
>(8), expected_commit_coeff_bytes, expected_commit_record_len)
2779 || !checked_mul_size(
static_cast<std::size_t
>(num_participants), expected_commit_record_len, expected_commits_len)
2780 || !checked_mul_size(
static_cast<std::size_t
>(num_participants),
static_cast<std::size_t
>(
UFSECP_FROST_SHARE_LEN), expected_shares_len)) {
2783 if (commits_len != expected_commits_len) {
2786 if (shares_len != expected_shares_len) {
2790 std::vector<secp256k1::FrostCommitment> commits;
2791 std::vector<uint8_t> seen_commit_from(
static_cast<size_t>(num_participants) + 1, 0);
2793 while (pos < commits_len) {
2796 if (pos + 8 > commits_len) {
2799 std::memcpy(&cc, all_commits + pos, 4); pos += 4;
2800 std::memcpy(&fc.
from, all_commits + pos, 4); pos += 4;
2801 if (cc != threshold) {
2804 if (fc.
from == 0 || fc.
from > num_participants) {
2807 if (seen_commit_from[fc.
from] != 0) {
2810 seen_commit_from[fc.
from] = 1;
2811 if (pos +
static_cast<size_t>(cc) * 33 > commits_len) {
2814 for (uint32_t j = 0; j < cc; ++j) {
2816 if (pt.is_infinity()) {
2822 commits.push_back(std::move(fc));
2824 if (commits.size() != num_participants) {
2832 if (n_shares != num_participants) {
2835 std::vector<secp256k1::FrostShare> shares(n_shares);
2836 auto erase_shares = [&]() {
2837 for (
auto& share : shares) {
2841 std::vector<uint8_t> seen_share_from(
static_cast<size_t>(num_participants) + 1, 0);
2842 for (
size_t i = 0; i < n_shares; ++i) {
2844 std::memcpy(&shares[i].from, s, 4);
2845 if (shares[i].from == 0 || shares[i].from > num_participants) {
2849 if (seen_share_from[shares[i].from] != 0) {
2853 seen_share_from[shares[i].from] = 1;
2854 shares[i].id = participant_id;
2860 shares[i].value = v;
2863 participant_id, commits, shares, threshold, num_participants);
2872 std::memcpy(keypkg_out, &kp.id, 4);
2873 std::memcpy(keypkg_out + 4, &kp.threshold, 4);
2874 std::memcpy(keypkg_out + 8, &kp.num_participants, 4);
2885 uint32_t participant_id,
2886 const uint8_t nonce_seed[32],
2891 if (participant_id == 0) {
2894 std::array<uint8_t, 32> seed_arr;
2895 std::memcpy(seed_arr.data(), nonce_seed, 32);
2897 auto h_bytes = nonce.hiding_nonce.to_bytes();
2898 auto b_bytes = nonce.binding_nonce.to_bytes();
2899 std::memcpy(nonce_out, h_bytes.data(), 32);
2900 std::memcpy(nonce_out + 32, b_bytes.data(), 32);
2906 std::memcpy(nonce_commit_out, &commit.id, 4);
2907 auto hp = commit.hiding_point.to_compressed();
2908 auto bp = commit.binding_point.to_compressed();
2909 std::memcpy(nonce_commit_out + 4, hp.data(), 33);
2910 std::memcpy(nonce_commit_out + 37, bp.data(), 33);
2933 const uint8_t msg32[32],
2934 const uint8_t* nonce_commits,
size_t n_signers,
2935 uint8_t partial_sig_out[36]) {
2936 if (!ctx || !keypkg || !nonce || !msg32 || !nonce_commits || !partial_sig_out) {
2940 if (n_signers == 0) {
2943 if (n_signers > kMaxBatchN) {
2946 std::size_t nc_total = 0;
2951 std::memcpy(&kp.
id, keypkg, 4);
2952 std::memcpy(&kp.
threshold, keypkg + 4, 4);
2984 std::array<uint8_t, 32> msg_arr;
2985 std::memcpy(msg_arr.data(), msg32, 32);
2986 std::vector<secp256k1::FrostNonceCommitment> ncs(n_signers);
2987 size_t self_commitment_count = 0;
2989 for (
size_t i = 0; i < n_signers; ++i) {
2991 std::memcpy(&ncs[i].
id, nc, 4);
2996 for (
size_t j = 0; j < i; ++j) {
2997 if (ncs[j].
id == ncs[i].
id) {
3003 if (ncs[i].
id == kp.
id) {
3004 ++self_commitment_count;
3007 if (ncs[i].hiding_point.is_infinity()) {
3012 if (ncs[i].binding_point.is_infinity()) {
3017 if (nc_err ==
UFSECP_OK && self_commitment_count != 1) {
3034 std::memcpy(partial_sig_out, &psig.id, 4);
3042 const uint8_t partial_sig[36],
3043 const uint8_t verification_share33[33],
3044 const uint8_t* nonce_commits,
size_t n_signers,
3045 const uint8_t msg32[32],
3046 const uint8_t group_pubkey33[33]) {
3047 if (!ctx || !partial_sig || !verification_share33 || !nonce_commits || !msg32 || !group_pubkey33) {
3051 if (n_signers == 0) {
3054 if (n_signers > kMaxBatchN) {
3057 std::size_t nc_total = 0;
3062 std::memcpy(&psig.
id, partial_sig, 4);
3072 if (vs.is_infinity()) {
3075 std::vector<secp256k1::FrostNonceCommitment> ncs(n_signers);
3077 size_t signer_matches = 0;
3078 for (
size_t i = 0; i < n_signers; ++i) {
3080 std::memcpy(&ncs[i].
id, nc, 4);
3081 if (ncs[i].
id == 0) {
3084 for (
size_t j = 0; j < i; ++j) {
3085 if (ncs[j].
id == ncs[i].
id) {
3090 if (ncs[i].hiding_point.is_infinity()) {
3094 if (ncs[i].binding_point.is_infinity()) {
3097 if (ncs[i].
id == psig.
id) {
3098 signer_commit = ncs[i];
3102 if (signer_matches != 1) {
3104 signer_matches == 0 ?
"partial_sig.id not found in nonce_commits"
3105 :
"partial_sig.id must appear exactly once in nonce_commits");
3108 if (gp.is_infinity()) {
3111 std::array<uint8_t, 32> msg_arr;
3112 std::memcpy(msg_arr.data(), msg32, 32);
3123 const uint8_t* partial_sigs,
size_t n,
3124 const uint8_t* nonce_commits,
size_t n_signers,
3125 const uint8_t group_pubkey33[33],
3126 const uint8_t msg32[32],
3127 uint8_t sig64_out[64]) {
3128 if (!ctx || !partial_sigs || !nonce_commits || !group_pubkey33 || !msg32 || !sig64_out) {
3135 if (n_signers == 0) {
3138 if (n != n_signers) {
3141 if (n > kMaxBatchN) {
3144 std::size_t psig_total = 0, nc_total = 0;
3145 if (!checked_mul_size(n, std::size_t{36}, psig_total)
3149 std::vector<secp256k1::FrostPartialSig> psigs(n);
3150 for (
size_t i = 0; i < n; ++i) {
3151 const uint8_t* ps = partial_sigs + i * 36;
3152 std::memcpy(&psigs[i].
id, ps, 4);
3153 if (psigs[i].
id == 0) {
3156 for (
size_t j = 0; j < i; ++j) {
3157 if (psigs[j].
id == psigs[i].
id) {
3167 std::vector<secp256k1::FrostNonceCommitment> ncs(n_signers);
3168 for (
size_t i = 0; i < n_signers; ++i) {
3170 std::memcpy(&ncs[i].
id, nc, 4);
3171 if (ncs[i].
id == 0) {
3174 for (
size_t j = 0; j < i; ++j) {
3175 if (ncs[j].
id == ncs[i].
id) {
3180 if (ncs[i].hiding_point.is_infinity()) {
3184 if (ncs[i].binding_point.is_infinity()) {
3188 for (
const auto& psig : psigs) {
3190 for (
const auto& nc : ncs) {
3191 if (nc.id == psig.id) {
3201 if (gp.is_infinity()) {
3204 std::array<uint8_t, 32> msg_arr;
3205 std::memcpy(msg_arr.data(), msg32, 32);
3207 auto bytes = sig.to_bytes();
3208 std::memcpy(sig64_out, bytes.data(), 64);
3219 const uint8_t privkey[32],
3220 const uint8_t msg32[32],
3221 const uint8_t adaptor_point33[33],
3222 const uint8_t aux_rand[32],
3224 if (!ctx || !privkey || !msg32 || !adaptor_point33 || !aux_rand || !pre_sig_out) {
3232 std::array<uint8_t, 32> msg_arr, aux_arr;
3233 std::memcpy(msg_arr.data(), msg32, 32);
3234 std::memcpy(aux_arr.data(), aux_rand, 32);
3236 if (ap.is_infinity()) {
3241 auto rhat = pre.R_hat.to_compressed();
3242 auto shat = pre.s_hat.to_bytes();
3243 std::memcpy(pre_sig_out, rhat.data(), 33);
3244 std::memcpy(pre_sig_out + 33, shat.data(), 32);
3246 std::memset(pre_sig_out + 65, 0, 32);
3247 pre_sig_out[65] = pre.needs_negation ? 1 : 0;
3254 const uint8_t pubkey_x[32],
3255 const uint8_t msg32[32],
3256 const uint8_t adaptor_point33[33]) {
3257 if (!ctx || !pre_sig || !pubkey_x || !msg32 || !adaptor_point33) {
3277 std::array<uint8_t, 32> pk_arr, msg_arr;
3278 std::memcpy(pk_arr.data(), pubkey_x, 32);
3279 std::memcpy(msg_arr.data(), msg32, 32);
3281 if (ap.is_infinity()) {
3293 const uint8_t adaptor_secret[32],
3294 uint8_t sig64_out[64]) {
3314 auto bytes = sig.to_bytes();
3315 std::memcpy(sig64_out, bytes.data(), 64);
3322 const uint8_t sig64[64],
3323 uint8_t secret32_out[32]) {
3352 const uint8_t privkey[32],
3353 const uint8_t msg32[32],
3354 const uint8_t adaptor_point33[33],
3356 if (!ctx || !privkey || !msg32 || !adaptor_point33 || !pre_sig_out) {
3364 std::array<uint8_t, 32> msg_arr;
3365 std::memcpy(msg_arr.data(), msg32, 32);
3367 if (ap.is_infinity()) {
3372 auto rhat = pre.R_hat.to_compressed();
3373 auto shat = pre.s_hat.to_bytes();
3374 auto r_bytes = pre.r.to_bytes();
3375 std::memcpy(pre_sig_out, rhat.data(), 33);
3376 std::memcpy(pre_sig_out + 33, shat.data(), 32);
3377 std::memcpy(pre_sig_out + 65, r_bytes.data(), 32);
3386 const uint8_t pubkey33[33],
3387 const uint8_t msg32[32],
3388 const uint8_t adaptor_point33[33]) {
3389 if (!ctx || !pre_sig || !pubkey33 || !msg32 || !adaptor_point33) {
3407 if (pk.is_infinity()) {
3410 std::array<uint8_t, 32> msg_arr;
3411 std::memcpy(msg_arr.data(), msg32, 32);
3413 if (ap.is_infinity()) {
3425 const uint8_t adaptor_secret[32],
3426 uint8_t sig64_out[64]) {
3448 auto compact = sig.to_compact();
3449 std::memcpy(sig64_out, compact.data(), 64);
3456 const uint8_t sig64[64],
3457 uint8_t secret32_out[32]) {
3473 std::array<uint8_t, 64> compact;
3474 std::memcpy(compact.data(), sig64, 64);
3493 const uint8_t value[32],
3494 const uint8_t blinding[32],
3495 uint8_t commitment33_out[33]) {
3506 auto comp = c.point.to_compressed();
3507 std::memcpy(commitment33_out, comp.data(), 33);
3512 const uint8_t commitment33[33],
3513 const uint8_t value[32],
3514 const uint8_t blinding[32]) {
3525 if (commit_pt.is_infinity()) {
3535 const uint8_t* pos,
size_t n_pos,
3536 const uint8_t* neg,
size_t n_neg) {
3539 if (n_pos > kMaxBatchN || n_neg > kMaxBatchN)
3541 std::size_t pos_bytes = 0, neg_bytes = 0;
3542 if (!checked_mul_size(n_pos, std::size_t{33}, pos_bytes)
3543 || !checked_mul_size(n_neg, std::size_t{33}, neg_bytes))
3546 std::vector<secp256k1::PedersenCommitment> pcs(n_pos), ncs(n_neg);
3547 for (
size_t i = 0; i < n_pos; ++i) {
3549 if (p.is_infinity()) {
3554 for (
size_t i = 0; i < n_neg; ++i) {
3556 if (p.is_infinity()) {
3569 const uint8_t* blinds_in,
size_t n_in,
3570 const uint8_t* blinds_out,
size_t n_out,
3571 uint8_t sum32_out[32]) {
3572 if (!ctx || (!blinds_in && n_in > 0) || (!blinds_out && n_out > 0) || !sum32_out) {
3576 if (n_in > kMaxBatchN || n_out > kMaxBatchN)
3578 std::size_t in_bytes = 0, out_bytes = 0;
3579 if (!checked_mul_size(n_in, std::size_t{32}, in_bytes)
3580 || !checked_mul_size(n_out, std::size_t{32}, out_bytes))
3583 std::vector<Scalar> ins(n_in), outs(n_out);
3584 for (
size_t i = 0; i < n_in; ++i) {
3589 for (
size_t i = 0; i < n_out; ++i) {
3601 const uint8_t value[32],
3602 const uint8_t blinding[32],
3603 const uint8_t switch_blind[32],
3604 uint8_t commitment33_out[33]) {
3605 if (!ctx || !value || !blinding || !switch_blind || !commitment33_out) {
3620 auto comp = c.point.to_compressed();
3621 std::memcpy(commitment33_out, comp.data(), 33);
3631 const uint8_t secret[32],
3632 const uint8_t pubkey33[33],
3633 const uint8_t msg32[32],
3634 const uint8_t aux_rand[32],
3636 if (!ctx || !secret || !pubkey33 || !msg32 || !aux_rand || !proof_out) {
3645 if (pk.is_infinity()) {
3648 std::array<uint8_t, 32> msg_arr, aux_arr;
3649 std::memcpy(msg_arr.data(), msg32, 32);
3650 std::memcpy(aux_arr.data(), aux_rand, 32);
3653 auto ser = proof.serialize();
3661 const uint8_t pubkey33[33],
3662 const uint8_t msg32[32]) {
3666 if (pk.is_infinity()) {
3673 std::array<uint8_t, 32> msg_arr;
3674 std::memcpy(msg_arr.data(), msg32, 32);
3683 const uint8_t secret[32],
3684 const uint8_t G33[33],
const uint8_t H33[33],
3685 const uint8_t P33[33],
const uint8_t Q33[33],
3686 const uint8_t aux_rand[32],
3688 if (!ctx || !secret || !G33 || !H33 || !P33 || !Q33 || !aux_rand || !proof_out) {
3700 if (G.is_infinity() || H.is_infinity() || P.is_infinity() || Q.is_infinity()) {
3703 std::array<uint8_t, 32> aux_arr;
3704 std::memcpy(aux_arr.data(), aux_rand, 32);
3707 auto ser = proof.serialize();
3715 const uint8_t G33[33],
const uint8_t H33[33],
3716 const uint8_t P33[33],
const uint8_t Q33[33]) {
3723 if (G.is_infinity() || H.is_infinity() || P.is_infinity() || Q.is_infinity()) {
3739 const uint8_t blinding[32],
3740 const uint8_t commitment33[33],
3741 const uint8_t aux_rand[32],
3742 uint8_t* proof_out,
size_t* proof_len) {
3743 if (!ctx || !blinding || !commitment33 || !aux_rand || !proof_out || !proof_len) {
3752 if (commit_pt.is_infinity()) {
3756 std::array<uint8_t, 32> aux_arr;
3757 std::memcpy(aux_arr.data(), aux_rand, 32);
3760 const size_t needed = 33*4 + 32*3 + 6*33 + 6*33 + 32*2;
3761 if (*proof_len < needed) {
3765 auto write_point = [&](
const Point& p) {
3766 auto c = p.to_compressed();
3767 std::memcpy(proof_out + off, c.data(), 33);
3770 auto write_scalar = [&](
const Scalar& s) {
3774 write_point(rp.A); write_point(rp.S);
3775 write_point(rp.T1); write_point(rp.T2);
3776 write_scalar(rp.tau_x); write_scalar(rp.mu); write_scalar(rp.t_hat);
3777 for (
int i = 0; i < 6; ++i) write_point(rp.L[i]);
3778 for (
int i = 0; i < 6; ++i) write_point(rp.R[i]);
3779 write_scalar(rp.a); write_scalar(rp.b);
3786 const uint8_t commitment33[33],
3787 const uint8_t* proof,
size_t proof_len) {
3791 const size_t expected = 33*4 + 32*3 + 6*33 + 6*33 + 32*2;
3792 if (proof_len < expected) {
3795 if (proof_len != expected) {
3800 bool point_ok =
true;
3801 auto read_point = [&]() ->
Point {
3803 if (p.is_infinity()) point_ok =
false;
3807 bool scalar_ok =
true;
3808 auto read_scalar = [&]() ->
Scalar {
3816 rp.
A = read_point(); rp.
S = read_point();
3817 rp.
T1 = read_point(); rp.
T2 = read_point();
3818 rp.
tau_x = read_scalar(); rp.
mu = read_scalar(); rp.
t_hat = read_scalar();
3819 for (
int i = 0; i < 6; ++i) rp.
L[i] = read_point();
3820 for (
int i = 0; i < 6; ++i) rp.
R[i] = read_point();
3821 rp.
a = read_scalar(); rp.
b = read_scalar();
3829 if (commit_pt.is_infinity()) {
3848 const uint8_t pubkey33[33],
3849 uint32_t coin_type,
int testnet,
3850 char* addr_out,
size_t* addr_len) {
3858 if (pk.is_infinity()) {
3866 if (*addr_len < addr.size() + 1) {
3869 std::memcpy(addr_out, addr.c_str(), addr.size() + 1);
3870 *addr_len = addr.size();
3877 const uint8_t* seed,
size_t seed_len,
3878 uint32_t coin_type, uint32_t account,
int change, uint32_t index,
3880 uint8_t* privkey32_out,
3881 uint8_t* pubkey33_out,
3882 char* addr_out,
size_t* addr_len) {
3885 if ((addr_out ==
nullptr) != (addr_len ==
nullptr)) {
3887 "addr_out and addr_len must both be null or both be non-null");
3889 if (seed_len < 16 || seed_len > 64) {
3899 if (!bip32_result.second) {
3902 auto master = bip32_result.first;
3903 const auto cleanup_keys = [&]() {
3909 master, *coin, account, change != 0, index);
3910 auto key = derived.first;
3911 bool const d_ok = derived.second;
3916 const auto cleanup_derived_key = [&]() {
3920 if (privkey32_out) {
3921 auto sk = key.private_key();
3925 auto pk = key.public_key();
3927 cleanup_derived_key();
3931 if (addr_out && addr_len) {
3933 if (*addr_len < addr.size() + 1) {
3936 std::memcpy(addr_out, addr.c_str(), addr.size() + 1);
3937 *addr_len = addr.size();
3944 const uint8_t privkey[32],
3945 uint32_t coin_type,
int testnet,
3946 char* wif_out,
size_t* wif_len) {
3963 if (*wif_len < wif.size() + 1) {
3966 std::memcpy(wif_out, wif.c_str(), wif.size() + 1);
3967 *wif_len = wif.size();
3973 const uint8_t* msg,
size_t msg_len,
3974 const uint8_t privkey[32],
3975 char* base64_out,
size_t* base64_len) {
3986 if (*base64_len < b64.size() + 1) {
3989 std::memcpy(base64_out, b64.c_str(), b64.size() + 1);
3990 *base64_len = b64.size();
3996 const uint8_t* msg,
size_t msg_len,
3997 const uint8_t pubkey33[33],
3998 const char* base64_sig) {
4002 if (pk.is_infinity()) {
4018 uint8_t digest32_out[32]) {
4021 std::memcpy(digest32_out, h.data(), 32);
4031 const uint8_t scan_privkey[32],
4032 const uint8_t spend_privkey[32],
4033 uint8_t scan_pubkey33_out[33],
4034 uint8_t spend_pubkey33_out[33],
4035 char* addr_out,
size_t* addr_len) {
4036 if (!ctx || !scan_privkey || !spend_privkey || !scan_pubkey33_out ||
4037 !spend_pubkey33_out || !addr_out || !addr_len) {
4042 Scalar scan_sk, spend_sk;
4043 auto cleanup = [&]() {
4056 auto scan_comp = spa.scan_pubkey.to_compressed();
4057 auto spend_comp = spa.spend_pubkey.to_compressed();
4058 std::memcpy(scan_pubkey33_out, scan_comp.data(), 33);
4059 std::memcpy(spend_pubkey33_out, spend_comp.data(), 33);
4061 auto addr_str = spa.encode();
4062 if (addr_str.size() >= *addr_len) {
4066 std::memcpy(addr_out, addr_str.c_str(), addr_str.size() + 1);
4067 *addr_len = addr_str.size();
4075 const uint8_t* input_privkeys,
size_t n_inputs,
4076 const uint8_t scan_pubkey33[33],
4077 const uint8_t spend_pubkey33[33],
4079 uint8_t output_pubkey33_out[33],
4080 uint8_t* tweak32_out) {
4081 if (!ctx || !input_privkeys || n_inputs == 0 || !scan_pubkey33 ||
4082 !spend_pubkey33 || !output_pubkey33_out) {
4087 std::size_t total = 0;
4088 if (!checked_mul_size(n_inputs, std::size_t{32}, total))
4093 std::vector<Scalar> privkeys;
4094 auto cleanup_privkeys = [&]() {
4095 for (
auto& sk : privkeys) {
4099 privkeys.reserve(n_inputs);
4100 for (
size_t i = 0; i < n_inputs; ++i) {
4107 privkeys.push_back(sk);
4120 if (output_point.is_infinity()) {
4125 auto out_comp = output_point.to_compressed();
4126 std::memcpy(output_pubkey33_out, out_comp.data(), 33);
4129 auto tweak_bytes = tweak.to_bytes();
4130 std::memcpy(tweak32_out, tweak_bytes.data(), 32);
4140 const uint8_t scan_privkey[32],
4141 const uint8_t spend_privkey[32],
4142 const uint8_t* input_pubkeys33,
size_t n_input_pubkeys,
4143 const uint8_t* output_xonly32,
size_t n_outputs,
4144 uint32_t* found_indices_out,
4145 uint8_t* found_privkeys_out,
4147 if (!ctx || !scan_privkey || !spend_privkey || !input_pubkeys33 ||
4148 !output_xonly32 || !n_found) {
4151 if (n_input_pubkeys == 0 || n_outputs == 0) {
4154 if (n_input_pubkeys > kMaxBatchN || n_outputs > kMaxBatchN)
4156 std::size_t pk_bytes = 0, out_bytes = 0;
4157 if (!checked_mul_size(n_input_pubkeys, std::size_t{33}, pk_bytes)
4158 || !checked_mul_size(n_outputs, std::size_t{32}, out_bytes))
4163 Scalar scan_sk, spend_sk;
4164 auto cleanup = [&]() {
4177 std::vector<Point> input_pks;
4178 input_pks.reserve(n_input_pubkeys);
4179 for (
size_t i = 0; i < n_input_pubkeys; ++i) {
4181 if (pk.is_infinity()) {
4185 input_pks.push_back(pk);
4189 std::vector<std::array<uint8_t, 32>> outputs;
4190 outputs.reserve(n_outputs);
4191 for (
size_t i = 0; i < n_outputs; ++i) {
4192 std::array<uint8_t, 32> x;
4193 std::memcpy(x.data(), output_xonly32 + i * 32, 32);
4194 outputs.push_back(x);
4199 size_t const capacity = *n_found;
4200 size_t const count = results.size() < capacity ? results.size() : capacity;
4201 *n_found = results.size();
4203 for (
size_t i = 0; i < count; ++i) {
4204 if (found_indices_out) found_indices_out[i] = results[i].first;
4205 if (found_privkeys_out) {
4206 auto key_bytes = results[i].second.to_bytes();
4207 std::memcpy(found_privkeys_out + i * 32, key_bytes.data(), 32);
4213 for (
auto& r : results) {
4228 const uint8_t recipient_pubkey33[33],
4229 const uint8_t* plaintext,
size_t plaintext_len,
4230 uint8_t* envelope_out,
size_t* envelope_len) {
4231 if (!ctx || !recipient_pubkey33 || !plaintext || !envelope_out || !envelope_len) {
4234 if (plaintext_len == 0) {
4243 if (*envelope_len < needed) {
4248 if (pk.is_infinity()) {
4253 if (envelope.empty()) {
4257 std::memcpy(envelope_out, envelope.data(), envelope.size());
4258 *envelope_len = envelope.size();
4265 const uint8_t privkey[32],
4266 const uint8_t* envelope,
size_t envelope_len,
4267 uint8_t* plaintext_out,
size_t* plaintext_len) {
4268 if (!ctx || !privkey || !envelope || !plaintext_out || !plaintext_len) {
4271 if (envelope_len < 82) {
4277 if (*plaintext_len < expected_pt_len) {
4293 std::memcpy(plaintext_out, pt.data(), pt.size());
4294 *plaintext_len = pt.size();
4303#if defined(SECP256K1_BIP324)
4305struct ufsecp_bip324_session {
4312 ufsecp_bip324_session** session_out,
4313 uint8_t ellswift64_out[64]) {
4316 *session_out =
nullptr;
4317 if (initiator != 0 && initiator != 1) {
4321 auto* sess =
new (std::nothrow) ufsecp_bip324_session;
4323 sess->cpp_session =
nullptr;
4326 if (!sess->cpp_session) {
4331 auto& enc = sess->cpp_session->our_ellswift_encoding();
4332 std::memcpy(ellswift64_out, enc.data(), 64);
4334 *session_out = sess;
4339 ufsecp_bip324_session* session,
4340 const uint8_t peer_ellswift64[64],
4341 uint8_t session_id32_out[32]) {
4344 if (!session->cpp_session->complete_handshake(peer_ellswift64)) {
4348 if (session_id32_out) {
4349 auto& sid = session->cpp_session->session_id();
4350 std::memcpy(session_id32_out, sid.data(), 32);
4356 ufsecp_bip324_session* session,
4357 const uint8_t* plaintext,
size_t plaintext_len,
4358 uint8_t* out,
size_t* out_len) {
4363 size_t const needed = plaintext_len + 19;
4366 auto enc = session->cpp_session->encrypt(plaintext, plaintext_len);
4369 std::memcpy(out, enc.data(), enc.size());
4370 *out_len = enc.size();
4376 ufsecp_bip324_session* session,
4377 const uint8_t* encrypted,
size_t encrypted_len,
4378 uint8_t* plaintext_out,
size_t* plaintext_len) {
4379 if (!session || !session->cpp_session || !encrypted || !plaintext_out || !plaintext_len)
4385 const uint8_t* header = encrypted;
4386 const uint8_t* payload_tag = encrypted + 3;
4387 const size_t payload_tag_len = encrypted_len - 3;
4389 std::vector<uint8_t> dec;
4390 if (!session->cpp_session->decrypt(header, payload_tag, payload_tag_len, dec)) {
4395 std::memcpy(plaintext_out, dec.data(), dec.size());
4396 *plaintext_len = dec.size();
4401void ufsecp_bip324_destroy(ufsecp_bip324_session* session) {
4403 if (session->cpp_session) {
4404 delete session->cpp_session;
4411 const uint8_t key[32],
const uint8_t nonce[12],
4412 const uint8_t* aad,
size_t aad_len,
4413 const uint8_t* plaintext,
size_t plaintext_len,
4414 uint8_t* out, uint8_t tag[16]) {
4420 key, nonce, aad, aad_len, plaintext, plaintext_len, out, tag);
4425 const uint8_t key[32],
const uint8_t nonce[12],
4426 const uint8_t* aad,
size_t aad_len,
4427 const uint8_t* ciphertext,
size_t ciphertext_len,
4428 const uint8_t tag[16], uint8_t* out) {
4434 key, nonce, aad, aad_len, ciphertext, ciphertext_len, tag, out);
4440 const uint8_t privkey[32],
4441 uint8_t encoding64_out[64]) {
4451 std::memcpy(encoding64_out, enc.data(), 64);
4459 const uint8_t ell_a64[64],
4460 const uint8_t ell_b64[64],
4461 const uint8_t our_privkey[32],
4463 uint8_t secret32_out[32]) {
4464 if (!ctx || !ell_a64 || !ell_b64 || !our_privkey || !secret32_out)
4474 std::memcpy(secret32_out, secret.data(), 32);
4486#if defined(SECP256K1_BUILD_ETHEREUM)
4489 uint8_t digest32_out[32]) {
4494 std::memcpy(digest32_out, hash.data(), 32);
4499 const uint8_t pubkey33[33],
4500 uint8_t addr20_out[20]) {
4510 std::memcpy(addr20_out, addr.data(), 20);
4515 const uint8_t pubkey33[33],
4516 char* addr_out,
size_t* addr_len) {
4520 if (*addr_len < 43) {
4531 std::memcpy(addr_out, addr_str.c_str(), addr_str.size());
4532 addr_out[addr_str.size()] =
'\0';
4533 *addr_len = addr_str.size();
4538ufsecp_error_t ufsecp_eth_personal_hash(
const uint8_t* msg,
size_t msg_len,
4539 uint8_t digest32_out[32]) {
4544 std::memcpy(digest32_out, hash.data(), 32);
4549 const uint8_t msg32[32],
4550 const uint8_t privkey[32],
4554 uint64_t chain_id) {
4555 if (!ctx || !msg32 || !privkey || !r_out || !s_out || !v_out) {
4565 std::array<uint8_t, 32> hash;
4566 std::memcpy(hash.data(), msg32, 32);
4569 std::memcpy(r_out, esig.r.data(), 32);
4570 std::memcpy(s_out, esig.s.data(), 32);
4578 const uint8_t msg32[32],
4579 const uint8_t r[32],
4580 const uint8_t s[32],
4582 uint8_t addr20_out[20]) {
4586 std::array<uint8_t, 32> hash, r_arr, s_arr;
4587 std::memcpy(hash.data(), msg32, 32);
4588 std::memcpy(r_arr.data(), r, 32);
4589 std::memcpy(s_arr.data(), s, 32);
4596 std::memcpy(addr20_out, addr.data(), 20);
4610 uint8_t* entropy_out,
size_t entropy_len) {
4612 if (entropy_len == 0 || entropy_len > 32) {
4623 if (parse_rc !=
UFSECP_OK)
return parse_rc;
4635 auto child_privkey = derived.private_key().to_bytes();
4640 static const uint8_t BIP85_KEY[] = {
'b',
'i',
'p',
'-',
'8',
'5'};
4644 std::memcpy(entropy_out, hmac.data(), entropy_len);
4653 uint32_t words, uint32_t language_index, uint32_t index,
4654 char* mnemonic_out,
size_t* mnemonic_len) {
4658 if (words != 12 && words != 18 && words != 24) {
4661 if (language_index != 0) {
4667 std::snprintf(path,
sizeof(path),
4668 "m/83696968'/39'/%u'/%u'/%u'",
4669 language_index, words, index);
4672 size_t const entropy_len = (
static_cast<size_t>(words) / 3) * 4;
4673 uint8_t entropy[32]{};
4684 if (!ok || mnemonic.empty()) {
4687 if (*mnemonic_len < mnemonic.size() + 1) {
4690 std::memcpy(mnemonic_out, mnemonic.c_str(), mnemonic.size() + 1);
4691 *mnemonic_len = mnemonic.size();
4702 const uint8_t privkey[32],
4703 const uint8_t* msg,
size_t msg_len,
4704 const uint8_t* aux_rand32,
4705 uint8_t sig64_out[64]) {
4712 static const uint8_t tag_data[] =
"BIP0340/msg";
4713 uint8_t msg_hash[32];
4718 h.
update(tag_hash.data(), 32);
4719 h.
update(tag_hash.data(), 32);
4720 if (msg && msg_len > 0) h.
update(msg, msg_len);
4722 std::memcpy(msg_hash, digest.data(), 32);
4726 uint8_t aux_arr[32];
4727 std::memcpy(aux_arr, aux_rand32, 32);
4733 const uint8_t pubkey_x[32],
4734 const uint8_t* msg,
size_t msg_len,
4735 const uint8_t sig64[64]) {
4740 static const uint8_t tag_data[] =
"BIP0340/msg";
4741 uint8_t msg_hash[32];
4745 h.
update(tag_hash.data(), 32);
4746 h.
update(tag_hash.data(), 32);
4747 if (msg && msg_len > 0) h.
update(msg, msg_len);
4749 std::memcpy(msg_hash, digest.data(), 32);
4761 const uint8_t privkey[32],
4763 const uint8_t* msg,
size_t msg_len,
4764 uint8_t* sig_out,
size_t* sig_len) {
4770 static const uint8_t bip322_tag[] =
"BIP0322-signed-message";
4771 uint8_t msg_hash[32];
4775 h.
update(tag_hash.data(), 32);
4776 h.
update(tag_hash.data(), 32);
4777 if (msg && msg_len > 0) h.
update(msg, msg_len);
4779 std::memcpy(msg_hash, digest.data(), 32);
4790 if (*sig_len < 64) {
4793 std::array<uint8_t, 32> msg_arr{}, aux_arr{};
4794 std::memcpy(msg_arr.data(), msg_hash, 32);
4799 auto bytes = sig.to_bytes();
4800 std::memcpy(sig_out, bytes.data(), 64);
4804 if (*sig_len < 65) {
4808 std::array<uint8_t, 32> msg_arr;
4809 std::memcpy(msg_arr.data(), msg_hash, 32);
4812 auto compact = sig.to_compact();
4813 std::memcpy(sig_out, compact.data(), 32);
4814 std::memcpy(sig_out + 32, compact.data() + 32, 32);
4824 const uint8_t* pubkey,
size_t pubkey_len,
4826 const uint8_t* msg,
size_t msg_len,
4827 const uint8_t* sig,
size_t sig_len) {
4832 static const uint8_t bip322_tag[] =
"BIP0322-signed-message";
4833 uint8_t msg_hash[32];
4837 h.
update(tag_hash.data(), 32);
4838 h.
update(tag_hash.data(), 32);
4839 if (msg && msg_len > 0) h.
update(msg, msg_len);
4841 std::memcpy(msg_hash, digest.data(), 32);
4846 if (pubkey_len != 32) {
4854 if (pubkey_len != 33) {
4864 std::array<uint8_t, 32> msg_arr;
4865 std::memcpy(msg_arr.data(), msg_hash, 32);
4867 std::array<uint8_t, 64> compact64;
4868 std::memcpy(compact64.data(), sig, 64);
4889static inline uint64_t siphash_rotl64(uint64_t x,
int b) {
4890 return (x << b) | (x >> (64 - b));
4893static uint64_t siphash24(
const uint8_t key[16],
const uint8_t* data,
size_t len) {
4895 std::memcpy(&k0, key, 8);
4896 std::memcpy(&k1, key + 8, 8);
4898 uint64_t v0 = k0 ^ 0x736f6d6570736575ULL;
4899 uint64_t v1 = k1 ^ 0x646f72616e646f6dULL;
4900 uint64_t v2 = k0 ^ 0x6c7967656e657261ULL;
4901 uint64_t v3 = k1 ^ 0x7465646279746573ULL;
4903 auto sipround = [&]() {
4904 v0 += v1; v1 = siphash_rotl64(v1, 13); v1 ^= v0; v0 = siphash_rotl64(v0, 32);
4905 v2 += v3; v3 = siphash_rotl64(v3, 16); v3 ^= v2;
4906 v0 += v3; v3 = siphash_rotl64(v3, 21); v3 ^= v0;
4907 v2 += v1; v1 = siphash_rotl64(v1, 17); v1 ^= v2; v2 = siphash_rotl64(v2, 32);
4911 for (; i + 8 <= len; i += 8) {
4913 std::memcpy(&m, data + i, 8);
4915 sipround(); sipround();
4919 uint64_t last =
static_cast<uint64_t
>(len & 0xff) << 56;
4920 size_t rem = len - i;
4921 for (
size_t j = 0; j < rem; ++j) last |= static_cast<uint64_t>(data[i + j]) << (j * 8);
4923 sipround(); sipround();
4926 sipround(); sipround(); sipround(); sipround();
4927 return v0 ^ v1 ^ v2 ^ v3;
4933static constexpr uint64_t
GCS_M = 784931ULL;
4937 uint8_t* out,
size_t* out_len) {
4938 std::vector<uint64_t> sorted = values;
4939 std::sort(sorted.begin(), sorted.end());
4943 std::vector<uint8_t> bits;
4944 bits.reserve(sorted.size() * 4);
4947 for (uint64_t v : sorted) {
4948 uint64_t delta = v - prev;
4950 uint64_t q = delta >>
GCS_P;
4951 uint64_t r = delta & ((1ULL <<
GCS_P) - 1);
4953 for (uint64_t i = 0; i < q; ++i) bits.push_back(1);
4956 for (
int i =
static_cast<int>(
GCS_P) - 1; i >= 0; --i) {
4957 bits.push_back(
static_cast<uint8_t
>((r >> i) & 1));
4962 size_t nbytes = (bits.size() + 7) / 8;
4963 if (*out_len < nbytes)
return false;
4964 std::memset(out, 0, nbytes);
4965 for (
size_t i = 0; i < bits.size(); ++i) {
4966 if (bits[i]) out[i / 8] |=
static_cast<uint8_t
>(0x80u >> (i % 8));
4972static bool gcs_decode(
const uint8_t* filter,
size_t filter_len,
size_t n_items,
4973 std::vector<uint64_t>& out) {
4975 out.reserve(n_items);
4979 auto read_bit = [&]() ->
int {
4980 if (bit_pos / 8 >= filter_len)
return -1;
4981 return (filter[bit_pos / 8] >> (7 - (bit_pos % 8))) & 1;
4985 for (
size_t i = 0; i < n_items; ++i) {
4990 if (b < 0)
return false;
4997 for (
size_t j = 0; j <
GCS_P; ++j) {
4999 if (b < 0)
return false;
5001 r = (r << 1) | static_cast<uint64_t>(b);
5003 uint64_t delta = (q <<
GCS_P) | r;
5005 out.push_back(prev);
5011 const uint8_t key[16],
5012 const uint8_t** data,
const size_t* data_sizes,
size_t count,
5013 uint8_t* filter_out,
size_t* filter_len) {
5019 uint64_t
const modulus =
static_cast<uint64_t
>(count) *
GCS_M;
5020 std::vector<uint64_t> hashed;
5021 hashed.reserve(count);
5023 for (
size_t i = 0; i < count; ++i) {
5024 uint64_t h = siphash24(key, data[i], data_sizes[i]);
5026 hashed.push_back(mulhi64(h, modulus));
5029 if (!
gcs_encode(hashed, filter_out, filter_len)) {
5037 const uint8_t key[16],
5038 const uint8_t* filter,
size_t filter_len,
5040 const uint8_t* item,
size_t item_len) {
5044 std::vector<uint64_t> decoded;
5045 if (!
gcs_decode(filter, filter_len, n_items, decoded)) {
5049 uint64_t
const modulus =
static_cast<uint64_t
>(n_items) *
GCS_M;
5050 uint64_t h = siphash24(key, item, item_len);
5051 uint64_t target = mulhi64(h, modulus);
5053 for (uint64_t v : decoded) {
5055 if (v > target)
break;
5062 const uint8_t key[16],
5063 const uint8_t* filter,
size_t filter_len,
5065 const uint8_t** query,
const size_t* query_sizes,
size_t query_count) {
5071 std::vector<uint64_t> decoded;
5072 if (!
gcs_decode(filter, filter_len, n_items, decoded)) {
5076 uint64_t
const modulus =
static_cast<uint64_t
>(n_items) *
GCS_M;
5077 for (
size_t qi = 0; qi < query_count; ++qi) {
5078 uint64_t h = siphash24(key, query[qi], query_sizes[qi]);
5079 uint64_t target = mulhi64(h, modulus);
5080 for (uint64_t v : decoded) {
5082 if (v > target)
break;
5095 const uint8_t sighash32[32],
5096 const uint8_t privkey[32],
5097 uint8_t sighash_type,
5098 uint8_t* sig_out,
size_t* sig_len) {
5107 if (*sig_len < 73) {
5112 std::array<uint8_t, 32> msg_arr;
5113 std::memcpy(msg_arr.data(), sighash32, 32);
5118 auto compact = sig.to_compact();
5119 std::array<uint8_t, 32> r_arr, s_arr;
5120 std::memcpy(r_arr.data(), compact.data(), 32);
5121 std::memcpy(s_arr.data(), compact.data() + 32, 32);
5126 uint8_t r_data[33], s_data[33];
5127 size_t r_len = 0, s_len = 0;
5130 while (r_start < 31 && r_arr[r_start] == 0) ++r_start;
5131 if (r_arr[r_start] & 0x80) { r_data[0] = 0x00; ++r_len; }
5132 for (
size_t i = r_start; i < 32; ++i) r_data[r_len++] = r_arr[i];
5135 while (s_start < 31 && s_arr[s_start] == 0) ++s_start;
5136 if (s_arr[s_start] & 0x80) { s_data[0] = 0x00; ++s_len; }
5137 for (
size_t i = s_start; i < 32; ++i) s_data[s_len++] = s_arr[i];
5139 size_t total = 2 + r_len + 2 + s_len;
5140 der[der_len++] = 0x30;
5141 der[der_len++] =
static_cast<uint8_t
>(total);
5142 der[der_len++] = 0x02;
5143 der[der_len++] =
static_cast<uint8_t
>(r_len);
5144 std::memcpy(der + der_len, r_data, r_len); der_len += r_len;
5145 der[der_len++] = 0x02;
5146 der[der_len++] =
static_cast<uint8_t
>(s_len);
5147 std::memcpy(der + der_len, s_data, s_len); der_len += s_len;
5149 if (*sig_len < der_len + 1) {
5152 std::memcpy(sig_out, der, der_len);
5153 sig_out[der_len] = sighash_type;
5154 *sig_len = der_len + 1;
5161 const uint8_t sighash32[32],
5162 const uint8_t privkey[32],
5163 uint8_t sighash_type,
5164 uint8_t* sig_out,
size_t* sig_len) {
5168 if (*sig_len < 65) {
5178 std::array<uint8_t, 32> msg_arr;
5179 std::memcpy(msg_arr.data(), sighash32, 32);
5182 auto compact = sig.to_compact();
5183 std::memcpy(sig_out, compact.data(), 32);
5184 std::memcpy(sig_out + 32, compact.data() + 32, 32);
5185 sig_out[64] = sighash_type;
5193 const uint8_t sighash32[32],
5194 const uint8_t privkey[32],
5195 uint8_t sighash_type,
5196 const uint8_t* aux_rand32,
5197 uint8_t* sig_out,
size_t* sig_len) {
5202 if (*sig_len < expected_len) {
5212 std::array<uint8_t, 32> msg_arr;
5213 std::array<uint8_t, 32> aux_arr{};
5214 std::memcpy(msg_arr.data(), sighash32, 32);
5215 if (aux_rand32) std::memcpy(aux_arr.data(), aux_rand32, 32);
5222 auto bytes = sig.to_bytes();
5223 std::memcpy(sig_out, bytes.data(), 64);
5225 sig_out[64] = sighash_type;
5237 const char* key_path,
5238 uint8_t privkey_out[32]) {
5255 const char* descriptor,
5258 char* addr_out,
size_t* addr_len) {
5263 std::string desc(descriptor);
5269 std::string outer_func;
5271 auto strip_func = [](
const std::string& s,
const std::string& fname, std::string& inner_out) ->
bool {
5272 if (s.size() <= fname.size() + 2)
return false;
5273 if (s.substr(0, fname.size() + 1) != fname +
"(")
return false;
5274 if (s.back() !=
')')
return false;
5275 inner_out = s.substr(fname.size() + 1, s.size() - fname.size() - 2);
5279 if (strip_func(desc,
"wpkh", inner)) {
5281 }
else if (desc.substr(0, 8) ==
"sh(wpkh(" && desc.back() ==
')' &&
5282 desc[desc.size()-2] ==
')') {
5284 inner = desc.substr(8, desc.size() - 10);
5285 }
else if (strip_func(desc,
"tr", inner)) {
5287 }
else if (strip_func(desc,
"pkh", inner)) {
5289 }
else if (strip_func(desc,
"pk", inner)) {
5298 key_out->
type = dtype;
5300 key_out->
path[0] =
'\0';
5303 std::string key_str, path_suffix;
5304 auto slash_pos = inner.find(
'/');
5305 if (slash_pos != std::string::npos) {
5306 key_str = inner.substr(0, slash_pos);
5307 path_suffix = inner.substr(slash_pos);
5313 for (
char c : path_suffix) {
5314 if (c !=
'/' && c !=
'*' && c !=
'\'' && !std::isdigit((
unsigned char)c) && c !=
';' && c !=
'<' && c !=
'>') {
5319 uint8_t pubkey33[33]{};
5322 if (key_str.size() == 111 || key_str.size() == 112 ||
5323 (key_str.substr(0,4) ==
"xpub" || key_str.substr(0,4) ==
"xprv" ||
5324 key_str.substr(0,4) ==
"tpub" || key_str.substr(0,4) ==
"tprv")) {
5330 if (!valid || data.size() < 78) {
5336 std::memcpy(bip32k.data, data.data(), 78);
5338 uint32_t ver = (uint32_t(data[0]) << 24) | (uint32_t(data[1]) << 16) |
5339 (uint32_t(data[2]) << 8) | uint32_t(data[3]);
5340 bip32k.is_private = (ver == 0x0488ADE4u || ver == 0x04358394u) ? 1 : 0;
5343 std::string derive_path =
"m";
5344 if (!path_suffix.empty()) {
5346 std::string ps = path_suffix;
5348 auto ab = ps.find(
'<');
5349 if (ab != std::string::npos) {
5350 auto ae = ps.find(
'>', ab);
5351 if (ae != std::string::npos) ps.replace(ab, ae - ab + 1,
"0");
5354 auto star = ps.find(
'*');
5355 if (star != std::string::npos) {
5356 ps.replace(star, 1, std::to_string(index));
5362 if (derive_path !=
"m") {
5373 }
else if (key_str.size() == 64 || key_str.size() == 66) {
5375 if (key_str.size() % 2 != 0) {
5378 size_t expected_bytes = key_str.size() / 2;
5379 if (expected_bytes != 33 && expected_bytes != 32) {
5382 for (
size_t i = 0; i < key_str.size(); i += 2) {
5383 unsigned int byte_val = 0;
5385 auto hexchar = [](
char c) ->
int {
5386 if (c >=
'0' && c <=
'9')
return c -
'0';
5387 if (c >=
'a' && c <=
'f')
return c -
'a' + 10;
5388 if (c >=
'A' && c <=
'F')
return c -
'A' + 10;
5391 int hi = hexchar(key_str[i]), lo = hexchar(key_str[i+1]);
5392 if (hi < 0 || lo < 0) {
5395 byte_val =
static_cast<unsigned int>(hi * 16 + lo);
5396 pubkey33[i / 2] =
static_cast<uint8_t
>(byte_val);
5405 if (pubkey33[0] == 0x02 || pubkey33[0] == 0x03) {
5406 std::memcpy(key_out->
pubkey, pubkey33 + 1, 32);
5409 std::memcpy(key_out->
pubkey, pubkey33, 32);
5413 std::memcpy(key_out->
pubkey, pubkey33, 33);
5417 if (path_suffix.size() <
sizeof(key_out->
path)) {
5418 std::memcpy(key_out->
path, path_suffix.c_str(), path_suffix.size() + 1);
5420 key_out->
path[0] =
'\0';
5424 if (addr_out && addr_len) {
5433 if (pubkey33[0] == 0x02 || pubkey33[0] == 0x03) {
5434 std::memcpy(xonly, pubkey33 + 1, 32);
5436 std::memcpy(xonly, pubkey33, 32);
5453 const char* descriptor,
5455 char* addr_out,
size_t* addr_len) {
SecureEraseGuard & operator=(const SecureEraseGuard &)=delete
SecureEraseGuard(const SecureEraseGuard &)=delete
SecureEraseGuard(T *value) noexcept
static digest_type hash(const void *data, std::size_t len) noexcept
static digest_type hash256(const void *data, std::size_t len) noexcept
digest_type finalize() noexcept
void update(const void *data, std::size_t len) noexcept
static digest_type hash(const void *data, std::size_t len) noexcept
static bool parse_bytes_strict(const std::uint8_t *bytes32, FieldElement &out) noexcept
static FieldElement from_uint64(std::uint64_t value)
static Point from_affine(const FieldElement &x, const FieldElement &y)
std::array< std::uint8_t, 65 > to_uncompressed() const
Point scalar_mul(const Scalar &scalar) const
bool is_infinity() const noexcept
Point add(const Point &other) const
std::array< std::uint8_t, 33 > to_compressed() const
static bool parse_bytes_strict_nonzero(const std::uint8_t *bytes32, Scalar &out) noexcept
std::array< std::uint8_t, 32 > to_bytes() const
static bool parse_bytes_strict(const std::uint8_t *bytes32, Scalar &out) noexcept
std::array< std::uint8_t, 20 > ethereum_address_bytes(const fast::Point &pubkey)
bool bitcoin_verify_message(const std::uint8_t *msg, std::size_t msg_len, const fast::Point &pubkey, const ECDSASignature &sig)
const CoinParams * find_by_coin_type(std::uint32_t coin_type)
std::string coin_wif_encode(const fast::Scalar &private_key, const CoinParams &coin, bool compressed=true, bool testnet=false)
std::string bitcoin_sig_to_base64(const RecoverableSignature &rsig, bool compressed=true)
BitcoinSigDecodeResult bitcoin_sig_from_base64(const std::string &base64)
std::string coin_address(const fast::Point &pubkey, const CoinParams &coin, bool testnet=false)
std::string ethereum_address(const fast::Point &pubkey)
EthSignature eth_sign_hash(const std::array< std::uint8_t, 32 > &hash, const fast::Scalar &private_key, std::uint64_t chain_id=0)
RecoverableSignature bitcoin_sign_message(const std::uint8_t *msg, std::size_t msg_len, const fast::Scalar &private_key)
std::pair< std::array< std::uint8_t, 20 >, bool > ecrecover(const std::array< std::uint8_t, 32 > &msg_hash, const std::array< std::uint8_t, 32 > &r, const std::array< std::uint8_t, 32 > &s, std::uint64_t v)
std::array< std::uint8_t, 32 > bitcoin_message_hash(const std::uint8_t *msg, std::size_t msg_len)
std::array< std::uint8_t, 32 > eip191_hash(const std::uint8_t *msg, std::size_t msg_len)
std::array< std::uint8_t, 32 > keccak256(const std::uint8_t *data, std::size_t len)
std::pair< ExtendedKey, bool > coin_derive_key(const ExtendedKey &master, const CoinParams &coin, std::uint32_t account=0, bool change=false, std::uint32_t address_index=0)
ECDSASignature ecdsa_sign_verified(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key)
Point generator_mul(const Scalar &k) noexcept
ECDSASignature ecdsa_sign(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key)
SchnorrSignature schnorr_sign(const SchnorrKeypair &kp, const std::array< std::uint8_t, 32 > &msg, const std::array< std::uint8_t, 32 > &aux_rand)
SchnorrSignature schnorr_sign_verified(const SchnorrKeypair &kp, const std::array< std::uint8_t, 32 > &msg, const std::array< std::uint8_t, 32 > &aux_rand)
SchnorrKeypair schnorr_keypair_create(const fast::Scalar &private_key)
void secure_erase(void *ptr, std::size_t len) noexcept
std::uint64_t mulhi64(std::uint64_t a, std::uint64_t b) noexcept
bool ensure_library_integrity(bool verbose=false)
RangeProof range_prove(std::uint64_t value, const fast::Scalar &blinding, const PedersenCommitment &commitment, const std::array< std::uint8_t, 32 > &aux_rand)
bool range_verify(const PedersenCommitment &commitment, const RangeProof &proof)
DLEQProof dleq_prove(const fast::Scalar &secret, const fast::Point &G, const fast::Point &H, const fast::Point &P, const fast::Point &Q, const std::array< std::uint8_t, 32 > &aux_rand)
bool dleq_verify(const DLEQProof &proof, const fast::Point &G, const fast::Point &H, const fast::Point &P, const fast::Point &Q)
KnowledgeProof knowledge_prove(const fast::Scalar &secret, const fast::Point &pubkey, const std::array< std::uint8_t, 32 > &msg, const std::array< std::uint8_t, 32 > &aux_rand)
bool knowledge_verify(const KnowledgeProof &proof, const fast::Point &pubkey, const std::array< std::uint8_t, 32 > &msg)
std::array< std::uint8_t, 32 > ecdh_compute_raw(const Scalar &private_key, const Point &public_key)
std::array< std::uint8_t, 32 > ecdh_compute_xonly(const Scalar &private_key, const Point &public_key)
SchnorrSignature frost_aggregate(const std::vector< FrostPartialSig > &partial_sigs, const std::vector< FrostNonceCommitment > &nonce_commitments, const fast::Point &group_public_key, const std::array< std::uint8_t, 32 > &msg)
std::pair< FrostKeyPackage, bool > frost_keygen_finalize(ParticipantId participant_id, const std::vector< FrostCommitment > &commitments, const std::vector< FrostShare > &received_shares, std::uint32_t threshold, std::uint32_t num_participants)
std::pair< Bip39Entropy, bool > bip39_mnemonic_to_entropy(const std::string &mnemonic)
std::array< std::uint8_t, 32 > ecdh_compute(const Scalar &private_key, const Point &public_key)
std::vector< std::uint8_t > ecies_decrypt(const fast::Scalar &privkey, const std::uint8_t *envelope, std::size_t envelope_len)
MuSig2KeyAggCtx musig2_key_agg(const std::vector< std::array< std::uint8_t, 32 > > &pubkeys)
std::string address_p2sh(const std::array< std::uint8_t, 20 > &script_hash, Network net=Network::Mainnet)
PedersenCommitment pedersen_switch_commit(const fast::Scalar &value, const fast::Scalar &blinding, const fast::Scalar &switch_blind)
MuSig2AggNonce musig2_nonce_agg(const std::vector< MuSig2PubNonce > &pub_nonces)
std::pair< ExtendedKey, bool > bip32_master_key(const std::uint8_t *seed, std::size_t seed_len)
RecoverableSignature ecdsa_sign_recoverable(const std::array< std::uint8_t, 32 > &msg_hash, const Scalar &private_key)
fast::Scalar musig2_partial_sign(MuSig2SecNonce &sec_nonce, const fast::Scalar &secret_key, const MuSig2KeyAggCtx &key_agg_ctx, const MuSig2Session &session, std::size_t signer_index)
std::array< std::uint8_t, 32 > ellswift_xdh(const std::uint8_t ell_a64[64], const std::uint8_t ell_b64[64], const Scalar &our_privkey, bool initiating) noexcept
std::string address_p2tr_raw(const std::array< std::uint8_t, 32 > &output_key_x, Network net=Network::Mainnet)
WitnessProgram parse_witness_program(const std::uint8_t *script, std::size_t script_len) noexcept
bool pedersen_verify_sum(const PedersenCommitment *commitments_pos, std::size_t n_pos, const PedersenCommitment *commitments_neg, std::size_t n_neg)
bool aead_chacha20_poly1305_decrypt(const std::uint8_t key[32], const std::uint8_t nonce[12], const std::uint8_t *aad, std::size_t aad_len, const std::uint8_t *ciphertext, std::size_t ciphertext_len, const std::uint8_t tag[16], std::uint8_t *out) noexcept
std::array< std::uint8_t, 32 > taproot_keypath_sighash(const TapSighashTxData &tx_data, std::size_t input_index, std::uint8_t hash_type, const std::uint8_t *annex=nullptr, std::size_t annex_len=0) noexcept
std::string address_p2sh_p2wpkh(const fast::Point &pubkey, Network net=Network::Mainnet)
bool schnorr_batch_verify(const SchnorrBatchEntry *entries, std::size_t n)
std::pair< fast::Point, fast::Scalar > silent_payment_create_output(const std::vector< fast::Scalar > &input_privkeys, const SilentPaymentAddress &recipient, std::uint32_t k=0)
void aead_chacha20_poly1305_encrypt(const std::uint8_t key[32], const std::uint8_t nonce[12], const std::uint8_t *aad, std::size_t aad_len, const std::uint8_t *plaintext, std::size_t plaintext_len, std::uint8_t *out, std::uint8_t tag[16]) noexcept
std::array< std::uint8_t, 34 > segwit_scriptpubkey_p2wsh(const std::uint8_t script_hash[32]) noexcept
bool frost_verify_partial(const FrostPartialSig &partial_sig, const FrostNonceCommitment &signer_commitment, const fast::Point &verification_share, const std::array< std::uint8_t, 32 > &msg, const std::vector< FrostNonceCommitment > &nonce_commitments, const fast::Point &group_public_key)
std::array< std::uint8_t, 32 > tagged_hash(const char *tag, const void *data, std::size_t len)
Scalar taproot_tweak_privkey(const Scalar &private_key, const std::uint8_t *merkle_root=nullptr, std::size_t merkle_root_len=0)
std::array< std::uint8_t, 25 > bip143_p2wpkh_script_code(const std::uint8_t pubkey_hash[20]) noexcept
std::pair< std::vector< std::uint8_t >, bool > base58check_decode(const std::string &encoded)
WIFDecodeResult wif_decode(const std::string &wif)
std::pair< std::string, bool > bip39_generate(std::size_t entropy_bytes, const std::uint8_t *entropy_in=nullptr)
std::array< std::uint8_t, 64 > hmac_sha512(const std::uint8_t *key, std::size_t key_len, const std::uint8_t *data, std::size_t data_len)
std::array< std::uint8_t, 32 > witness_commitment(const std::array< std::uint8_t, 32 > &witness_root, const std::array< std::uint8_t, 32 > &witness_nonce) noexcept
std::array< std::uint8_t, 20 > hash160(const std::uint8_t *data, std::size_t len)
std::array< std::uint8_t, 32 > tapscript_sighash(const TapSighashTxData &tx_data, std::size_t input_index, std::uint8_t hash_type, const std::array< std::uint8_t, 32 > &tapleaf_hash, std::uint8_t key_version, std::uint32_t code_separator_pos, const std::uint8_t *annex=nullptr, std::size_t annex_len=0) noexcept
std::vector< std::size_t > schnorr_batch_identify_invalid(const SchnorrBatchEntry *entries, std::size_t n)
std::array< std::uint8_t, 32 > witness_script_hash(const std::uint8_t *script, std::size_t script_len) noexcept
std::string address_p2wpkh(const fast::Point &pubkey, Network net=Network::Mainnet)
fast::Point shamir_trick(const fast::Scalar &a, const fast::Point &P, const fast::Scalar &b, const fast::Point &Q)
bool schnorr_verify(const std::uint8_t *pubkey_x32, const std::uint8_t *msg32, const SchnorrSignature &sig)
std::pair< FrostCommitment, std::vector< FrostShare > > frost_keygen_begin(ParticipantId participant_id, std::uint32_t threshold, std::uint32_t num_participants, const std::array< std::uint8_t, 32 > &secret_seed)
std::array< std::uint8_t, 64 > ellswift_create(const Scalar &privkey)
std::string address_p2pkh(const fast::Point &pubkey, Network net=Network::Mainnet)
bool ecdsa_batch_verify(const ECDSABatchEntry *entries, std::size_t n)
fast::Point multi_scalar_mul(const fast::Scalar *scalars, const fast::Point *points, std::size_t n)
bool schnorr_adaptor_verify(const SchnorrAdaptorSig &pre_sig, const std::array< std::uint8_t, 32 > &pubkey_x, const std::array< std::uint8_t, 32 > &msg, const fast::Point &adaptor_point)
SchnorrAdaptorSig schnorr_adaptor_sign(const fast::Scalar &private_key, const std::array< std::uint8_t, 32 > &msg, const fast::Point &adaptor_point, const std::array< std::uint8_t, 32 > &aux_rand)
bool bip39_validate(const std::string &mnemonic)
ECDSAAdaptorSig ecdsa_adaptor_sign(const fast::Scalar &private_key, const std::array< std::uint8_t, 32 > &msg_hash, const fast::Point &adaptor_point)
bool pedersen_verify(const PedersenCommitment &commitment, const fast::Scalar &value, const fast::Scalar &blinding)
fast::Scalar pedersen_blind_sum(const fast::Scalar *blinds_in, std::size_t n_in, const fast::Scalar *blinds_out, std::size_t n_out)
PedersenCommitment pedersen_commit(const fast::Scalar &value, const fast::Scalar &blinding)
ECDSASignature ecdsa_adaptor_adapt(const ECDSAAdaptorSig &pre_sig, const fast::Scalar &adaptor_secret)
std::pair< fast::Scalar, bool > ecdsa_adaptor_extract(const ECDSAAdaptorSig &pre_sig, const ECDSASignature &sig)
MuSig2Session musig2_start_sign_session(const MuSig2AggNonce &agg_nonce, const MuSig2KeyAggCtx &key_agg_ctx, const std::array< std::uint8_t, 32 > &msg)
std::array< std::uint8_t, 22 > segwit_scriptpubkey_p2wpkh(const std::uint8_t pubkey_hash[20]) noexcept
std::vector< std::size_t > ecdsa_batch_identify_invalid(const ECDSABatchEntry *entries, std::size_t n)
std::pair< std::array< std::uint8_t, 64 >, bool > bip39_mnemonic_to_seed(const std::string &mnemonic, const std::string &passphrase="")
std::string wif_encode(const fast::Scalar &private_key, bool compressed=true, Network net=Network::Mainnet)
std::pair< fast::Scalar, bool > schnorr_adaptor_extract(const SchnorrAdaptorSig &pre_sig, const SchnorrSignature &sig)
bool musig2_partial_verify(const fast::Scalar &partial_sig, const MuSig2PubNonce &pub_nonce, const std::array< std::uint8_t, 32 > &pubkey, const MuSig2KeyAggCtx &key_agg_ctx, const MuSig2Session &session, std::size_t signer_index)
std::vector< std::pair< std::uint32_t, fast::Scalar > > silent_payment_scan(const fast::Scalar &scan_privkey, const fast::Scalar &spend_privkey, const std::vector< fast::Point > &input_pubkeys, const std::vector< std::array< std::uint8_t, 32 > > &output_pubkeys)
std::pair< std::array< std::uint8_t, 32 >, int > taproot_output_key(const std::array< std::uint8_t, 32 > &internal_key_x, const std::uint8_t *merkle_root=nullptr, std::size_t merkle_root_len=0)
SchnorrSignature schnorr_adaptor_adapt(const SchnorrAdaptorSig &pre_sig, const fast::Scalar &adaptor_secret)
std::pair< Point, bool > ecdsa_recover(const std::array< std::uint8_t, 32 > &msg_hash, const ECDSASignature &sig, int recid)
std::pair< MuSig2SecNonce, MuSig2PubNonce > musig2_nonce_gen(const fast::Scalar &secret_key, const std::array< std::uint8_t, 32 > &pub_key, const std::array< std::uint8_t, 32 > &agg_pub_key, const std::array< std::uint8_t, 32 > &msg, const std::uint8_t *extra_input=nullptr)
std::array< std::uint8_t, 32 > bip143_sighash(const Bip143Preimage &preimage, const Outpoint &outpoint, const std::uint8_t *script_code, std::size_t script_code_len, std::uint64_t value, std::uint32_t sequence, std::uint32_t sighash_type) noexcept
std::pair< FrostNonce, FrostNonceCommitment > frost_sign_nonce_gen(ParticipantId participant_id, const std::array< std::uint8_t, 32 > &nonce_seed)
bool taproot_verify_commitment(const std::array< std::uint8_t, 32 > &output_key_x, int output_key_parity, const std::array< std::uint8_t, 32 > &internal_key_x, const std::uint8_t *merkle_root=nullptr, std::size_t merkle_root_len=0)
FrostPartialSig frost_sign(const FrostKeyPackage &key_pkg, FrostNonce &nonce, const std::array< std::uint8_t, 32 > &msg, const std::vector< FrostNonceCommitment > &nonce_commitments)
std::array< std::uint8_t, 32 > schnorr_pubkey(const fast::Scalar &private_key)
ECDSASignature ecdsa_sign(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key)
bool ecdsa_adaptor_verify(const ECDSAAdaptorSig &pre_sig, const fast::Point &public_key, const std::array< std::uint8_t, 32 > &msg_hash, const fast::Point &adaptor_point)
std::array< std::uint8_t, 64 > musig2_partial_sig_agg(const std::vector< fast::Scalar > &partial_sigs, const MuSig2Session &session)
bool ecdsa_verify(const std::uint8_t *msg_hash32, const fast::Point &public_key, const ECDSASignature &sig)
std::array< std::uint8_t, 34 > segwit_scriptpubkey_p2tr(const std::uint8_t output_key[32]) noexcept
std::vector< std::uint8_t > ecies_encrypt(const fast::Point &recipient_pubkey, const std::uint8_t *plaintext, std::size_t plaintext_len)
SilentPaymentAddress silent_payment_address(const fast::Scalar &scan_privkey, const fast::Scalar &spend_privkey)
bool is_witness_program(const std::uint8_t *script, std::size_t script_len) noexcept
std::pair< ExtendedKey, bool > bip32_derive_path(const ExtendedKey &master, const std::string &path)
std::pair< std::array< std::uint8_t, 72 >, std::size_t > to_der() const
static bool parse_compact_strict(const std::uint8_t *data64, ECDSASignature &out) noexcept
static ECDSASignature from_compact(const std::uint8_t *data64)
std::array< std::uint8_t, 78 > serialize() const
std::vector< fast::Point > coeffs
fast::Point verification_share
std::uint32_t num_participants
fast::Scalar signing_share
fast::Point group_public_key
fast::Scalar binding_nonce
fast::Scalar hiding_nonce
std::vector< fast::Scalar > key_coefficients
std::array< std::uint8_t, 32 > Q_x
static MuSig2PubNonce deserialize(const std::array< std::uint8_t, 66 > &data)
static bool parse_strict(const std::uint8_t *data64, SchnorrSignature &out) noexcept
static bool deserialize(const std::uint8_t *data64, DLEQProof &out)
static bool deserialize(const std::uint8_t *data64, KnowledgeProof &out)
std::array< fast::Point, RANGE_PROOF_LOG2 > R
std::array< fast::Point, RANGE_PROOF_LOG2 > L
uint8_t data[UFSECP_BIP32_SERIALIZED_LEN]
#define UFSECP_FROST_NONCE_COMMIT_LEN
#define UFSECP_NET_MAINNET
#define UFSECP_ZK_KNOWLEDGE_PROOF_LEN
#define UFSECP_MUSIG2_SECNONCE_LEN
#define UFSECP_ECIES_OVERHEAD
#define UFSECP_ZK_DLEQ_PROOF_LEN
#define UFSECP_FROST_NONCE_LEN
#define UFSECP_SIGHASH_DEFAULT
@ UFSECP_BIP322_ADDR_P2TR
#define UFSECP_MUSIG2_KEYAGG_LEN
#define UFSECP_FROST_KEYPKG_LEN
#define UFSECP_FROST_SHARE_LEN
#define UFSECP_MUSIG2_AGGNONCE_LEN
#define UFSECP_NET_TESTNET
#define UFSECP_MUSIG2_PUBNONCE_LEN
#define UFSECP_ECDSA_ADAPTOR_SIG_LEN
#define UFSECP_MUSIG2_SESSION_LEN
#define UFSECP_SCHNORR_ADAPTOR_SIG_LEN
#define UFSECP_ERR_INTERNAL
#define UFSECP_ERR_BAD_PUBKEY
#define UFSECP_ERR_NULL_ARG
#define UFSECP_ERR_VERIFY_FAIL
#define UFSECP_ERR_NOT_FOUND
#define UFSECP_ERR_SELFTEST
#define UFSECP_ERR_BAD_SIG
#define UFSECP_ERR_BUF_TOO_SMALL
#define UFSECP_ERR_BAD_INPUT
#define UFSECP_ERR_BAD_KEY
ufsecp_error_t ufsecp_bip143_sighash(ufsecp_ctx *ctx, uint32_t version, const uint8_t hash_prevouts[32], const uint8_t hash_sequence[32], const uint8_t outpoint_txid[32], uint32_t outpoint_vout, const uint8_t *script_code, size_t script_code_len, uint64_t value, uint32_t sequence, const uint8_t hash_outputs[32], uint32_t locktime, uint32_t sighash_type, uint8_t sighash_out[32])
ufsecp_error_t ufsecp_seckey_negate(ufsecp_ctx *ctx, uint8_t privkey[32])
void ufsecp_ctx_destroy(ufsecp_ctx *ctx)
ufsecp_error_t ufsecp_descriptor_address(ufsecp_ctx *ctx, const char *descriptor, uint32_t index, char *addr_out, size_t *addr_len)
ufsecp_error_t ufsecp_hash160(const uint8_t *data, size_t len, uint8_t digest20_out[20])
ufsecp_error_t ufsecp_musig2_nonce_gen(ufsecp_ctx *ctx, const uint8_t privkey[32], const uint8_t pubkey32[32], const uint8_t agg_pubkey32[32], const uint8_t msg32[32], const uint8_t extra_in[32], uint8_t secnonce_out[UFSECP_MUSIG2_SECNONCE_LEN], uint8_t pubnonce_out[UFSECP_MUSIG2_PUBNONCE_LEN])
ufsecp_error_t ufsecp_silent_payment_scan(ufsecp_ctx *ctx, const uint8_t scan_privkey[32], const uint8_t spend_privkey[32], const uint8_t *input_pubkeys33, size_t n_input_pubkeys, const uint8_t *output_xonly32, size_t n_outputs, uint32_t *found_indices_out, uint8_t *found_privkeys_out, size_t *n_found)
ufsecp_error_t ufsecp_bip39_to_seed(ufsecp_ctx *ctx, const char *mnemonic, const char *passphrase, uint8_t seed64_out[64])
ufsecp_error_t ufsecp_musig2_partial_verify(ufsecp_ctx *ctx, const uint8_t partial_sig32[32], const uint8_t pubnonce[UFSECP_MUSIG2_PUBNONCE_LEN], const uint8_t pubkey32[32], const uint8_t keyagg[UFSECP_MUSIG2_KEYAGG_LEN], const uint8_t session[UFSECP_MUSIG2_SESSION_LEN], size_t signer_index)
ufsecp_error_t ufsecp_ecdsa_sign(ufsecp_ctx *ctx, const uint8_t msg32[32], const uint8_t privkey[32], uint8_t sig64_out[64])
ufsecp_error_t ufsecp_musig2_start_sign_session(ufsecp_ctx *ctx, const uint8_t aggnonce[UFSECP_MUSIG2_AGGNONCE_LEN], const uint8_t keyagg[UFSECP_MUSIG2_KEYAGG_LEN], const uint8_t msg32[32], uint8_t session_out[UFSECP_MUSIG2_SESSION_LEN])
ufsecp_error_t ufsecp_pedersen_commit(ufsecp_ctx *ctx, const uint8_t value[32], const uint8_t blinding[32], uint8_t commitment33_out[33])
ufsecp_error_t ufsecp_gcs_match_any(const uint8_t key[16], const uint8_t *filter, size_t filter_len, size_t n_items, const uint8_t **query, const size_t *query_sizes, size_t query_count)
static bool scalar_parse_strict_nonzero(const uint8_t b[32], Scalar &out)
ufsecp_error_t ufsecp_schnorr_verify(ufsecp_ctx *ctx, const uint8_t msg32[32], const uint8_t sig64[64], const uint8_t pubkey_x[32])
ufsecp_error_t ufsecp_schnorr_verify_msg(ufsecp_ctx *ctx, const uint8_t pubkey_x[32], const uint8_t *msg, size_t msg_len, const uint8_t sig64[64])
static bool scalar_parse_strict(const uint8_t b[32], Scalar &out)
static void point_to_compressed(const Point &p, uint8_t out[33])
ufsecp_error_t ufsecp_taproot_tweak_seckey(ufsecp_ctx *ctx, const uint8_t privkey[32], const uint8_t *merkle_root, uint8_t tweaked32_out[32])
ufsecp_error_t ufsecp_descriptor_parse(ufsecp_ctx *ctx, const char *descriptor, uint32_t index, ufsecp_desc_key *key_out, char *addr_out, size_t *addr_len)
ufsecp_error_t ufsecp_psbt_derive_key(ufsecp_ctx *ctx, const ufsecp_bip32_key *master_xprv, const char *key_path, uint8_t privkey_out[32])
ufsecp_error_t ufsecp_musig2_partial_sign(ufsecp_ctx *ctx, uint8_t secnonce[UFSECP_MUSIG2_SECNONCE_LEN], const uint8_t privkey[32], const uint8_t keyagg[UFSECP_MUSIG2_KEYAGG_LEN], const uint8_t session[UFSECP_MUSIG2_SESSION_LEN], size_t signer_index, uint8_t partial_sig32_out[32])
ufsecp_error_t ufsecp_pubkey_add(ufsecp_ctx *ctx, const uint8_t a33[33], const uint8_t b33[33], uint8_t out33[33])
ufsecp_error_t ufsecp_sha512(const uint8_t *data, size_t len, uint8_t digest64_out[64])
ufsecp_error_t ufsecp_pubkey_combine(ufsecp_ctx *ctx, const uint8_t *pubkeys, size_t n, uint8_t out33[33])
ufsecp_error_t ufsecp_bip144_witness_commitment(const uint8_t witness_root[32], const uint8_t witness_nonce[32], uint8_t commitment_out[32])
ufsecp_error_t ufsecp_bip143_p2wpkh_script_code(const uint8_t pubkey_hash[20], uint8_t script_code_out[25])
static ufsecp_error_t pubkey_create_core(ufsecp_ctx *ctx, const uint8_t privkey[32], Point &pk_out)
size_t ufsecp_ctx_size(void)
ufsecp_error_t ufsecp_ecdh(ufsecp_ctx *ctx, const uint8_t privkey[32], const uint8_t pubkey33[33], uint8_t secret32_out[32])
ufsecp_error_t ufsecp_bip322_sign(ufsecp_ctx *ctx, const uint8_t privkey[32], ufsecp_bip322_addr_type addr_type, const uint8_t *msg, size_t msg_len, uint8_t *sig_out, size_t *sig_len)
static void extkey_to_uf(const secp256k1::ExtendedKey &ek, ufsecp_bip32_key *out)
ufsecp_error_t ufsecp_tapscript_sighash(ufsecp_ctx *ctx, uint32_t version, uint32_t locktime, size_t input_count, const uint8_t *prevout_txids, const uint32_t *prevout_vouts, const uint64_t *input_amounts, const uint32_t *input_sequences, const uint8_t *const *input_spks, const size_t *input_spk_lens, size_t output_count, const uint64_t *output_values, const uint8_t *const *output_spks, const size_t *output_spk_lens, size_t input_index, uint8_t hash_type, const uint8_t tapleaf_hash[32], uint8_t key_version, uint32_t code_separator_pos, const uint8_t *annex, size_t annex_len, uint8_t sighash_out[32])
ufsecp_error_t ufsecp_bip32_privkey(ufsecp_ctx *ctx, const ufsecp_bip32_key *key, uint8_t privkey32_out[32])
ufsecp_error_t ufsecp_schnorr_adaptor_extract(ufsecp_ctx *ctx, const uint8_t pre_sig[UFSECP_SCHNORR_ADAPTOR_SIG_LEN], const uint8_t sig64[64], uint8_t secret32_out[32])
ufsecp_error_t ufsecp_musig2_partial_sig_agg(ufsecp_ctx *ctx, const uint8_t *partial_sigs, size_t n, const uint8_t session[UFSECP_MUSIG2_SESSION_LEN], uint8_t sig64_out[64])
ufsecp_error_t ufsecp_ecies_decrypt(ufsecp_ctx *ctx, const uint8_t privkey[32], const uint8_t *envelope, size_t envelope_len, uint8_t *plaintext_out, size_t *plaintext_len)
ufsecp_error_t ufsecp_last_error(const ufsecp_ctx *ctx)
ufsecp_error_t ufsecp_ecdsa_verify(ufsecp_ctx *ctx, const uint8_t msg32[32], const uint8_t sig64[64], const uint8_t pubkey33[33])
static void ctx_clear_err(ufsecp_ctx *ctx)
ufsecp_error_t ufsecp_pubkey_tweak_add(ufsecp_ctx *ctx, const uint8_t pubkey33[33], const uint8_t tweak[32], uint8_t out33[33])
ufsecp_error_t ufsecp_schnorr_sign(ufsecp_ctx *ctx, const uint8_t msg32[32], const uint8_t privkey[32], const uint8_t aux_rand[32], uint8_t sig64_out[64])
ufsecp_error_t ufsecp_schnorr_adaptor_adapt(ufsecp_ctx *ctx, const uint8_t pre_sig[UFSECP_SCHNORR_ADAPTOR_SIG_LEN], const uint8_t adaptor_secret[32], uint8_t sig64_out[64])
ufsecp_error_t ufsecp_coin_derive_from_seed(ufsecp_ctx *ctx, const uint8_t *seed, size_t seed_len, uint32_t coin_type, uint32_t account, int change, uint32_t index, int testnet, uint8_t *privkey32_out, uint8_t *pubkey33_out, char *addr_out, size_t *addr_len)
static bool skip_compact_bytes(const uint8_t *buf, size_t len, size_t &offset)
ufsecp_error_t ufsecp_ecdsa_sign_recoverable(ufsecp_ctx *ctx, const uint8_t msg32[32], const uint8_t privkey[32], uint8_t sig64_out[64], int *recid_out)
ufsecp_error_t ufsecp_pedersen_verify(ufsecp_ctx *ctx, const uint8_t commitment33[33], const uint8_t value[32], const uint8_t blinding[32])
ufsecp_error_t ufsecp_bip85_entropy(ufsecp_ctx *ctx, const ufsecp_bip32_key *master_xprv, const char *path, uint8_t *entropy_out, size_t entropy_len)
ufsecp_error_t ufsecp_bip85_bip39(ufsecp_ctx *ctx, const ufsecp_bip32_key *master_xprv, uint32_t words, uint32_t language_index, uint32_t index, char *mnemonic_out, size_t *mnemonic_len)
ufsecp_error_t ufsecp_silent_payment_address(ufsecp_ctx *ctx, const uint8_t scan_privkey[32], const uint8_t spend_privkey[32], uint8_t scan_pubkey33_out[33], uint8_t spend_pubkey33_out[33], char *addr_out, size_t *addr_len)
ufsecp_error_t ufsecp_taproot_keypath_sighash(ufsecp_ctx *ctx, uint32_t version, uint32_t locktime, size_t input_count, const uint8_t *prevout_txids, const uint32_t *prevout_vouts, const uint64_t *input_amounts, const uint32_t *input_sequences, const uint8_t *const *input_spks, const size_t *input_spk_lens, size_t output_count, const uint64_t *output_values, const uint8_t *const *output_spks, const size_t *output_spk_lens, size_t input_index, uint8_t hash_type, const uint8_t *annex, size_t annex_len, uint8_t sighash_out[32])
ufsecp_error_t ufsecp_schnorr_sign_verified(ufsecp_ctx *ctx, const uint8_t msg32[32], const uint8_t privkey[32], const uint8_t aux_rand[32], uint8_t sig64_out[64])
const char * ufsecp_last_error_msg(const ufsecp_ctx *ctx)
ufsecp_error_t ufsecp_segwit_witness_script_hash(const uint8_t *script, size_t script_len, uint8_t hash_out[32])
ufsecp_error_t ufsecp_ecdh_xonly(ufsecp_ctx *ctx, const uint8_t privkey[32], const uint8_t pubkey33[33], uint8_t secret32_out[32])
static ufsecp_error_t parse_bip32_key(ufsecp_ctx *ctx, const ufsecp_bip32_key *key, secp256k1::ExtendedKey &out)
ufsecp_error_t ufsecp_addr_p2pkh(ufsecp_ctx *ctx, const uint8_t pubkey33[33], int network, char *addr_out, size_t *addr_len)
ufsecp_error_t ufsecp_ecdsa_sign_verified(ufsecp_ctx *ctx, const uint8_t msg32[32], const uint8_t privkey[32], uint8_t sig64_out[64])
ufsecp_error_t ufsecp_seckey_tweak_add(ufsecp_ctx *ctx, uint8_t privkey[32], const uint8_t tweak[32])
ufsecp_error_t ufsecp_taproot_output_key(ufsecp_ctx *ctx, const uint8_t internal_x[32], const uint8_t *merkle_root, uint8_t output_x_out[32], int *parity_out)
static bool gcs_encode(const std::vector< uint64_t > &values, uint8_t *out, size_t *out_len)
ufsecp_error_t ufsecp_silent_payment_create_output(ufsecp_ctx *ctx, const uint8_t *input_privkeys, size_t n_inputs, const uint8_t scan_pubkey33[33], const uint8_t spend_pubkey33[33], uint32_t k, uint8_t output_pubkey33_out[33], uint8_t *tweak32_out)
ufsecp_error_t ufsecp_addr_p2tr(ufsecp_ctx *ctx, const uint8_t internal_key_x[32], int network, char *addr_out, size_t *addr_len)
ufsecp_error_t ufsecp_frost_sign_nonce_gen(ufsecp_ctx *ctx, uint32_t participant_id, const uint8_t nonce_seed[32], uint8_t nonce_out[UFSECP_FROST_NONCE_LEN], uint8_t nonce_commit_out[UFSECP_FROST_NONCE_COMMIT_LEN])
ufsecp_error_t ufsecp_psbt_sign_legacy(ufsecp_ctx *ctx, const uint8_t sighash32[32], const uint8_t privkey[32], uint8_t sighash_type, uint8_t *sig_out, size_t *sig_len)
ufsecp_error_t ufsecp_ecdsa_sig_to_der(ufsecp_ctx *ctx, const uint8_t sig64[64], uint8_t *der_out, size_t *der_len)
const char * ufsecp_version_string(void)
ufsecp_error_t ufsecp_pedersen_blind_sum(ufsecp_ctx *ctx, const uint8_t *blinds_in, size_t n_in, const uint8_t *blinds_out, size_t n_out, uint8_t sum32_out[32])
ufsecp_error_t ufsecp_sha256(const uint8_t *data, size_t len, uint8_t digest32_out[32])
ufsecp_error_t ufsecp_zk_dleq_verify(ufsecp_ctx *ctx, const uint8_t proof[UFSECP_ZK_DLEQ_PROOF_LEN], const uint8_t G33[33], const uint8_t H33[33], const uint8_t P33[33], const uint8_t Q33[33])
ufsecp_error_t ufsecp_segwit_parse_program(const uint8_t *script, size_t script_len, int *version_out, uint8_t *program_out, size_t *program_len_out)
ufsecp_error_t ufsecp_bip32_derive(ufsecp_ctx *ctx, const ufsecp_bip32_key *parent, uint32_t index, ufsecp_bip32_key *child_out)
ufsecp_error_t ufsecp_schnorr_batch_verify(ufsecp_ctx *ctx, const uint8_t *entries, size_t n)
ufsecp_error_t ufsecp_bip32_derive_path(ufsecp_ctx *ctx, const ufsecp_bip32_key *master, const char *path, ufsecp_bip32_key *key_out)
ufsecp_error_t ufsecp_musig2_nonce_agg(ufsecp_ctx *ctx, const uint8_t *pubnonces, size_t n, uint8_t aggnonce_out[UFSECP_MUSIG2_AGGNONCE_LEN])
ufsecp_error_t ufsecp_schnorr_sign_batch(ufsecp_ctx *ctx, size_t count, const uint8_t *msgs32, const uint8_t *privkeys32, const uint8_t *aux_rands32, uint8_t *sigs64_out)
ufsecp_error_t ufsecp_ecdsa_batch_verify(ufsecp_ctx *ctx, const uint8_t *entries, size_t n)
ufsecp_error_t ufsecp_multi_scalar_mul(ufsecp_ctx *ctx, const uint8_t *scalars, const uint8_t *points, size_t n, uint8_t out33[33])
ufsecp_error_t ufsecp_pubkey_create_uncompressed(ufsecp_ctx *ctx, const uint8_t privkey[32], uint8_t pubkey65_out[65])
ufsecp_error_t ufsecp_zk_knowledge_prove(ufsecp_ctx *ctx, const uint8_t secret[32], const uint8_t pubkey33[33], const uint8_t msg32[32], const uint8_t aux_rand[32], uint8_t proof_out[UFSECP_ZK_KNOWLEDGE_PROOF_LEN])
static void scalar_to_bytes(const Scalar &s, uint8_t out[32])
ufsecp_error_t ufsecp_coin_address(ufsecp_ctx *ctx, const uint8_t pubkey33[33], uint32_t coin_type, int testnet, char *addr_out, size_t *addr_len)
ufsecp_error_t ufsecp_psbt_sign_segwit(ufsecp_ctx *ctx, const uint8_t sighash32[32], const uint8_t privkey[32], uint8_t sighash_type, uint8_t *sig_out, size_t *sig_len)
unsigned int ufsecp_version(void)
ufsecp_error_t ufsecp_frost_aggregate(ufsecp_ctx *ctx, const uint8_t *partial_sigs, size_t n, const uint8_t *nonce_commits, size_t n_signers, const uint8_t group_pubkey33[33], const uint8_t msg32[32], uint8_t sig64_out[64])
ufsecp_error_t ufsecp_ecdsa_batch_identify_invalid(ufsecp_ctx *ctx, const uint8_t *entries, size_t n, size_t *invalid_out, size_t *invalid_count)
ufsecp_error_t ufsecp_bip144_wtxid(ufsecp_ctx *ctx, const uint8_t *raw_tx, size_t raw_tx_len, uint8_t wtxid_out[32])
ufsecp_error_t ufsecp_seckey_verify(const ufsecp_ctx *ctx, const uint8_t privkey[32])
ufsecp_error_t ufsecp_btc_message_hash(const uint8_t *msg, size_t msg_len, uint8_t digest32_out[32])
ufsecp_error_t ufsecp_pubkey_negate(ufsecp_ctx *ctx, const uint8_t pubkey33[33], uint8_t out33[33])
static void secure_erase_scalar_vector(std::vector< Scalar > &values)
static secp256k1::Network to_network(int n)
ufsecp_error_t ufsecp_ecdsa_adaptor_verify(ufsecp_ctx *ctx, const uint8_t pre_sig[UFSECP_ECDSA_ADAPTOR_SIG_LEN], const uint8_t pubkey33[33], const uint8_t msg32[32], const uint8_t adaptor_point33[33])
ufsecp_error_t ufsecp_coin_wif_encode(ufsecp_ctx *ctx, const uint8_t privkey[32], uint32_t coin_type, int testnet, char *wif_out, size_t *wif_len)
ufsecp_error_t ufsecp_psbt_sign_taproot(ufsecp_ctx *ctx, const uint8_t sighash32[32], const uint8_t privkey[32], uint8_t sighash_type, const uint8_t *aux_rand32, uint8_t *sig_out, size_t *sig_len)
int ufsecp_segwit_is_witness_program(const uint8_t *script, size_t script_len)
ufsecp_error_t ufsecp_pubkey_tweak_mul(ufsecp_ctx *ctx, const uint8_t pubkey33[33], const uint8_t tweak[32], uint8_t out33[33])
ufsecp_error_t ufsecp_btc_message_sign(ufsecp_ctx *ctx, const uint8_t *msg, size_t msg_len, const uint8_t privkey[32], char *base64_out, size_t *base64_len)
ufsecp_error_t ufsecp_zk_range_prove(ufsecp_ctx *ctx, uint64_t value, const uint8_t blinding[32], const uint8_t commitment33[33], const uint8_t aux_rand[32], uint8_t *proof_out, size_t *proof_len)
static constexpr uint64_t GCS_P
ufsecp_error_t ufsecp_bip32_master(ufsecp_ctx *ctx, const uint8_t *seed, size_t seed_len, ufsecp_bip32_key *key_out)
ufsecp_error_t ufsecp_pubkey_create(ufsecp_ctx *ctx, const uint8_t privkey[32], uint8_t pubkey33_out[33])
ufsecp_error_t ufsecp_zk_dleq_prove(ufsecp_ctx *ctx, const uint8_t secret[32], const uint8_t G33[33], const uint8_t H33[33], const uint8_t P33[33], const uint8_t Q33[33], const uint8_t aux_rand[32], uint8_t proof_out[UFSECP_ZK_DLEQ_PROOF_LEN])
ufsecp_error_t ufsecp_bip144_txid(ufsecp_ctx *ctx, const uint8_t *raw_tx, size_t raw_tx_len, uint8_t txid_out[32])
ufsecp_error_t ufsecp_ecdh_raw(ufsecp_ctx *ctx, const uint8_t privkey[32], const uint8_t pubkey33[33], uint8_t secret32_out[32])
ufsecp_error_t ufsecp_pedersen_switch_commit(ufsecp_ctx *ctx, const uint8_t value[32], const uint8_t blinding[32], const uint8_t switch_blind[32], uint8_t commitment33_out[33])
ufsecp_error_t ufsecp_seckey_tweak_mul(ufsecp_ctx *ctx, uint8_t privkey[32], const uint8_t tweak[32])
ufsecp_error_t ufsecp_addr_p2sh(const uint8_t *redeem_script, size_t redeem_script_len, int network, char *addr_out, size_t *addr_len)
static ufsecp_error_t ecdh_parse_args(ufsecp_ctx *ctx, const uint8_t privkey[32], const uint8_t pubkey33[33], Scalar &sk, Point &pk)
ufsecp_error_t ufsecp_musig2_key_agg(ufsecp_ctx *ctx, const uint8_t *pubkeys, size_t n, uint8_t keyagg_out[UFSECP_MUSIG2_KEYAGG_LEN], uint8_t agg_pubkey32_out[32])
ufsecp_error_t ufsecp_bip39_validate(const ufsecp_ctx *ctx, const char *mnemonic)
static secp256k1::TapSighashTxData build_tap_tx_data(uint32_t version, uint32_t locktime, size_t input_count, const uint8_t *prevout_txids_flat, const uint32_t *prevout_vouts, const uint64_t *input_amounts, const uint32_t *input_sequences, const uint8_t *const *input_spks, const size_t *input_spk_lens, size_t output_count, const uint64_t *output_values, const uint8_t *const *output_spks, const size_t *output_spk_lens, std::vector< std::array< uint8_t, 32 > > &txid_storage)
static constexpr uint64_t GCS_M
#define UFSECP_CATCH_RETURN(ctx_ptr)
ufsecp_error_t ufsecp_gcs_match(const uint8_t key[16], const uint8_t *filter, size_t filter_len, size_t n_items, const uint8_t *item, size_t item_len)
ufsecp_error_t ufsecp_btc_message_verify(ufsecp_ctx *ctx, const uint8_t *msg, size_t msg_len, const uint8_t pubkey33[33], const char *base64_sig)
ufsecp_error_t ufsecp_bip322_verify(ufsecp_ctx *ctx, const uint8_t *pubkey, size_t pubkey_len, ufsecp_bip322_addr_type addr_type, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len)
const char * ufsecp_error_str(ufsecp_error_t err)
ufsecp_error_t ufsecp_bip39_generate(ufsecp_ctx *ctx, size_t entropy_bytes, const uint8_t *entropy_in, char *mnemonic_out, size_t *mnemonic_len)
ufsecp_error_t ufsecp_schnorr_adaptor_verify(ufsecp_ctx *ctx, const uint8_t pre_sig[UFSECP_SCHNORR_ADAPTOR_SIG_LEN], const uint8_t pubkey_x[32], const uint8_t msg32[32], const uint8_t adaptor_point33[33])
ufsecp_error_t ufsecp_addr_p2wpkh(ufsecp_ctx *ctx, const uint8_t pubkey33[33], int network, char *addr_out, size_t *addr_len)
ufsecp_error_t ufsecp_ecies_encrypt(ufsecp_ctx *ctx, const uint8_t recipient_pubkey33[33], const uint8_t *plaintext, size_t plaintext_len, uint8_t *envelope_out, size_t *envelope_len)
ufsecp_error_t ufsecp_tagged_hash(const char *tag, const uint8_t *data, size_t len, uint8_t digest32_out[32])
ufsecp_error_t ufsecp_ecdsa_sign_batch(ufsecp_ctx *ctx, size_t count, const uint8_t *msgs32, const uint8_t *privkeys32, uint8_t *sigs64_out)
ufsecp_error_t ufsecp_addr_p2sh_p2wpkh(ufsecp_ctx *ctx, const uint8_t pubkey33[33], int network, char *addr_out, size_t *addr_len)
ufsecp_error_t ufsecp_pubkey_xonly(ufsecp_ctx *ctx, const uint8_t privkey[32], uint8_t xonly32_out[32])
ufsecp_error_t ufsecp_frost_verify_partial(ufsecp_ctx *ctx, const uint8_t partial_sig[36], const uint8_t verification_share33[33], const uint8_t *nonce_commits, size_t n_signers, const uint8_t msg32[32], const uint8_t group_pubkey33[33])
ufsecp_error_t ufsecp_schnorr_adaptor_sign(ufsecp_ctx *ctx, const uint8_t privkey[32], const uint8_t msg32[32], const uint8_t adaptor_point33[33], const uint8_t aux_rand[32], uint8_t pre_sig_out[UFSECP_SCHNORR_ADAPTOR_SIG_LEN])
ufsecp_error_t ufsecp_zk_range_verify(ufsecp_ctx *ctx, const uint8_t commitment33[33], const uint8_t *proof, size_t proof_len)
ufsecp_error_t ufsecp_ecdsa_recover(ufsecp_ctx *ctx, const uint8_t msg32[32], const uint8_t sig64[64], int recid, uint8_t pubkey33_out[33])
ufsecp_error_t ufsecp_segwit_p2tr_spk(const uint8_t output_key[32], uint8_t spk_out[34])
ufsecp_error_t ufsecp_ctx_clone(const ufsecp_ctx *src, ufsecp_ctx **ctx_out)
ufsecp_error_t ufsecp_pedersen_verify_sum(ufsecp_ctx *ctx, const uint8_t *pos, size_t n_pos, const uint8_t *neg, size_t n_neg)
ufsecp_error_t ufsecp_taproot_verify(ufsecp_ctx *ctx, const uint8_t output_x[32], int output_parity, const uint8_t internal_x[32], const uint8_t *merkle_root, size_t merkle_root_len)
static bool gcs_decode(const uint8_t *filter, size_t filter_len, size_t n_items, std::vector< uint64_t > &out)
ufsecp_error_t ufsecp_frost_sign(ufsecp_ctx *ctx, const uint8_t keypkg[UFSECP_FROST_KEYPKG_LEN], const uint8_t nonce[UFSECP_FROST_NONCE_LEN], const uint8_t msg32[32], const uint8_t *nonce_commits, size_t n_signers, uint8_t partial_sig_out[36])
Sign a FROST round-2 partial signature.
ufsecp_error_t ufsecp_segwit_p2wpkh_spk(const uint8_t pubkey_hash[20], uint8_t spk_out[22])
ufsecp_error_t ufsecp_segwit_p2wsh_spk(const uint8_t script_hash[32], uint8_t spk_out[34])
unsigned int ufsecp_abi_version(void)
ufsecp_error_t ufsecp_ecdsa_sig_from_der(ufsecp_ctx *ctx, const uint8_t *der, size_t der_len, uint8_t sig64_out[64])
static secp256k1::ExtendedKey extkey_from_uf(const ufsecp_bip32_key *k)
ufsecp_error_t ufsecp_shamir_trick(ufsecp_ctx *ctx, const uint8_t a[32], const uint8_t P33[33], const uint8_t b[32], const uint8_t Q33[33], uint8_t out33[33])
ufsecp_error_t ufsecp_zk_knowledge_verify(ufsecp_ctx *ctx, const uint8_t proof[UFSECP_ZK_KNOWLEDGE_PROOF_LEN], const uint8_t pubkey33[33], const uint8_t msg32[32])
ufsecp_error_t ufsecp_ecdsa_adaptor_adapt(ufsecp_ctx *ctx, const uint8_t pre_sig[UFSECP_ECDSA_ADAPTOR_SIG_LEN], const uint8_t adaptor_secret[32], uint8_t sig64_out[64])
ufsecp_error_t ufsecp_ecdsa_adaptor_extract(ufsecp_ctx *ctx, const uint8_t pre_sig[UFSECP_ECDSA_ADAPTOR_SIG_LEN], const uint8_t sig64[64], uint8_t secret32_out[32])
ufsecp_error_t ufsecp_schnorr_sign_msg(ufsecp_ctx *ctx, const uint8_t privkey[32], const uint8_t *msg, size_t msg_len, const uint8_t *aux_rand32, uint8_t sig64_out[64])
static Point point_from_compressed(const uint8_t pub[33])
ufsecp_error_t ufsecp_wif_decode(ufsecp_ctx *ctx, const char *wif, uint8_t privkey32_out[32], int *compressed_out, int *network_out)
static const secp256k1::coins::CoinParams * find_coin(uint32_t coin_type)
ufsecp_error_t ufsecp_wif_encode(ufsecp_ctx *ctx, const uint8_t privkey[32], int compressed, int network, char *wif_out, size_t *wif_len)
ufsecp_error_t ufsecp_gcs_build(const uint8_t key[16], const uint8_t **data, const size_t *data_sizes, size_t count, uint8_t *filter_out, size_t *filter_len)
ufsecp_error_t ufsecp_ecdsa_adaptor_sign(ufsecp_ctx *ctx, const uint8_t privkey[32], const uint8_t msg32[32], const uint8_t adaptor_point33[33], uint8_t pre_sig_out[UFSECP_ECDSA_ADAPTOR_SIG_LEN])
static ufsecp_error_t ctx_set_err(ufsecp_ctx *ctx, ufsecp_error_t err, const char *msg)
ufsecp_error_t ufsecp_frost_keygen_begin(ufsecp_ctx *ctx, uint32_t participant_id, uint32_t threshold, uint32_t num_participants, const uint8_t seed[32], uint8_t *commits_out, size_t *commits_len, uint8_t *shares_out, size_t *shares_len)
ufsecp_error_t ufsecp_bip32_pubkey(ufsecp_ctx *ctx, const ufsecp_bip32_key *key, uint8_t pubkey33_out[33])
ufsecp_error_t ufsecp_pubkey_parse(ufsecp_ctx *ctx, const uint8_t *input, size_t input_len, uint8_t pubkey33_out[33])
ufsecp_error_t ufsecp_frost_keygen_finalize(ufsecp_ctx *ctx, uint32_t participant_id, const uint8_t *all_commits, size_t commits_len, const uint8_t *received_shares, size_t shares_len, uint32_t threshold, uint32_t num_participants, uint8_t keypkg_out[UFSECP_FROST_KEYPKG_LEN])
ufsecp_error_t ufsecp_schnorr_batch_identify_invalid(ufsecp_ctx *ctx, const uint8_t *entries, size_t n, size_t *invalid_out, size_t *invalid_count)
ufsecp_error_t ufsecp_ctx_create(ufsecp_ctx **ctx_out)
ufsecp_error_t ufsecp_bip39_to_entropy(ufsecp_ctx *ctx, const char *mnemonic, uint8_t *entropy_out, size_t *entropy_len)
static size_t read_compact_size(const uint8_t *buf, size_t len, size_t &offset, uint64_t &val)
#define UFSECP_VERSION_PACKED
#define UFSECP_VERSION_STRING
#define UFSECP_ABI_VERSION