// SPDX-Licence-Identifier: EUPL-1.2
// Stable C API for go-blockchain CGo bindings.
// Go code calls ONLY these functions — no C++ types cross this boundary.
#ifndef CRYPTONOTE_BRIDGE_H
#define CRYPTONOTE_BRIDGE_H

#include <stdint.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

// ── Hashing ───────────────────────────────────────────────
void bridge_fast_hash(const uint8_t *data, size_t len, uint8_t hash[32]);

// ── Scalar Operations ────────────────────────────────────
// Reduce a 32-byte scalar modulo the Ed25519 group order l.
void cn_sc_reduce32(uint8_t key[32]);

// ── Key Operations ────────────────────────────────────────
int cn_generate_keys(uint8_t pub[32], uint8_t sec[32]);
int cn_secret_to_public(const uint8_t sec[32], uint8_t pub[32]);
int cn_check_key(const uint8_t pub[32]);

// ── Key Derivation ────────────────────────────────────────
int cn_generate_key_derivation(const uint8_t pub[32], const uint8_t sec[32],
                               uint8_t derivation[32]);
int cn_derive_public_key(const uint8_t derivation[32], uint64_t index,
                         const uint8_t base[32], uint8_t derived[32]);
int cn_derive_secret_key(const uint8_t derivation[32], uint64_t index,
                         const uint8_t base[32], uint8_t derived[32]);

// ── Key Images ────────────────────────────────────────────
int cn_generate_key_image(const uint8_t pub[32], const uint8_t sec[32],
                          uint8_t image[32]);
int cn_validate_key_image(const uint8_t image[32]);

// ── Standard Signatures ───────────────────────────────────
int cn_generate_signature(const uint8_t hash[32], const uint8_t pub[32],
                          const uint8_t sec[32], uint8_t sig[64]);
int cn_check_signature(const uint8_t hash[32], const uint8_t pub[32],
                       const uint8_t sig[64]);

// ── Ring Signatures (NLSAG) ──────────────────────────────
int cn_generate_ring_signature(const uint8_t hash[32], const uint8_t image[32],
                               const uint8_t *pubs, size_t pubs_count,
                               const uint8_t sec[32], size_t sec_index,
                               uint8_t *sigs);
int cn_check_ring_signature(const uint8_t hash[32], const uint8_t image[32],
                            const uint8_t *pubs, size_t pubs_count,
                            const uint8_t *sigs);

// ── Point Helpers ─────────────────────────────────────────
// Multiply a curve point by the cofactor 8 (for clearing small subgroup component).
int cn_point_mul8(const uint8_t pk[32], uint8_t result[32]);
// Premultiply by 1/8 (cofactor inverse). Stored form on-chain.
int cn_point_div8(const uint8_t pk[32], uint8_t result[32]);

// Subtract two curve points: result = a - b.
int cn_point_sub(const uint8_t a[32], const uint8_t b[32], uint8_t result[32]);

// ── CLSAG Verification (HF4+) ────────────────────────────
// Ring entries are flat arrays of 32-byte public keys per entry:
//   GG:    [stealth_addr(32) | amount_commitment(32)] per entry = 64 bytes
//   GGX:   [stealth(32) | commitment(32) | blinded_asset_id(32)] = 96 bytes
//   GGXXG: [stealth(32) | commitment(32) | blinded_asset_id(32) | concealing(32)] = 128 bytes
// Signature layout (flat):
//   GG:    c(32) | r[ring_size*32] | K1(32) = 64 + ring_size*32
//   GGX:   c(32) | r_g[ring_size*32] | r_x[ring_size*32] | K1(32) | K2(32) = 96 + ring_size*64
//   GGXXG: c(32) | r_g[ring_size*32] | r_x[ring_size*32] | K1(32) | K2(32) | K3(32) | K4(32) = 160 + ring_size*64

size_t cn_clsag_gg_sig_size(size_t ring_size);
int cn_clsag_gg_generate(const uint8_t hash[32], const uint8_t *ring,
                          size_t ring_size, const uint8_t pseudo_out[32],
                          const uint8_t ki[32], const uint8_t secret_x[32],
                          const uint8_t secret_f[32], size_t secret_index,
                          uint8_t *sig);
int cn_clsag_gg_verify(const uint8_t hash[32], const uint8_t *ring,
                        size_t ring_size, const uint8_t pseudo_out[32],
                        const uint8_t ki[32], const uint8_t *sig);

size_t cn_clsag_ggx_sig_size(size_t ring_size);
int cn_clsag_ggx_verify(const uint8_t hash[32], const uint8_t *ring,
                         size_t ring_size, const uint8_t pseudo_out_commitment[32],
                         const uint8_t pseudo_out_asset_id[32],
                         const uint8_t ki[32], const uint8_t *sig);

size_t cn_clsag_ggxxg_sig_size(size_t ring_size);
int cn_clsag_ggxxg_verify(const uint8_t hash[32], const uint8_t *ring,
                           size_t ring_size, const uint8_t pseudo_out_commitment[32],
                           const uint8_t pseudo_out_asset_id[32],
                           const uint8_t extended_commitment[32],
                           const uint8_t ki[32], const uint8_t *sig);

// ── Range Proofs (BPP — Bulletproofs++) ──────────────────
// Verifies a BPP range proof (1 delta). Used for zc_outs_range_proof in
// post-HF4 transactions. proof is the wire-serialised bpp_signature:
//   varint(len(L)) + L[]*32 + varint(len(R)) + R[]*32
//   + A0(32) + A(32) + B(32) + r(32) + s(32) + delta(32)
// commitments is a flat array of 32-byte public keys — the
// amount_commitments_for_rp_aggregation (E'_j, premultiplied by 1/8).
// Uses bpp_crypto_trait_ZC_out (generators UGX, N=64, values_max=32).
// Returns 0 on success, 1 on verification failure or deserialisation error.
int cn_bpp_verify(const uint8_t *proof, size_t proof_len,
                  const uint8_t *commitments, size_t num_commitments);

// ── Range Proofs (BPPE — Bulletproofs++ Enhanced) ────────
// Verifies a BPPE range proof (2 deltas). Used for Zarcanum PoS E_range_proof.
// proof is the wire-serialised bppe_signature:
//   varint(len(L)) + L[]*32 + varint(len(R)) + R[]*32
//   + A0(32) + A(32) + B(32) + r(32) + s(32) + delta_1(32) + delta_2(32)
// commitments is a flat array of 32-byte public keys (premultiplied by 1/8).
// Uses bpp_crypto_trait_Zarcanum (N=128, values_max=16).
// Returns 0 on success, 1 on verification failure or deserialisation error.
int cn_bppe_verify(const uint8_t *proof, size_t proof_len,
                   const uint8_t *commitments, size_t num_commitments);

// ── BGE One-out-of-Many ───────────────────────────────────
// Verifies a BGE one-out-of-many proof. proof is wire-serialised BGE_proof:
//   A(32) + B(32) + varint(len(Pk)) + Pk[]*32
//   + varint(len(f)) + f[]*32 + y(32) + z(32)
// ring is a flat array of 32-byte public keys. context is a 32-byte hash.
// Returns 0 on success, 1 on verification failure or deserialisation error.
int cn_bge_verify(const uint8_t context[32], const uint8_t *ring,
                  size_t ring_size, const uint8_t *proof, size_t proof_len);

// ── Generic Double Schnorr ────────────────────────────────
// Generates a generic_double_schnorr_sig from zarcanum.h.
// a_is_x selects the generator pair:
//   0 -> (G, G)
//   1 -> (X, G)
// proof must point to a 96-byte buffer.
int cn_double_schnorr_generate(int a_is_x, const uint8_t hash[32],
                               const uint8_t secret_a[32],
                               const uint8_t secret_b[32],
                               uint8_t *proof, size_t proof_len);

// Verifies a generic_double_schnorr_sig from zarcanum.h.
// a_is_x selects the generator pair:
//   0 -> (G, G)
//   1 -> (X, G)
// Returns 0 on success, 1 on verification failure or deserialisation error.
int cn_double_schnorr_verify(int a_is_x, const uint8_t hash[32],
                             const uint8_t a[32], const uint8_t b[32],
                             const uint8_t *proof, size_t proof_len);

// ── Zarcanum PoS ──────────────────────────────────────────
// Legacy compatibility wrapper for the historical proof-only API.
int cn_zarcanum_verify(const uint8_t hash[32], const uint8_t *proof,
                       size_t proof_len);

// Full Zarcanum verification entrypoint.
// ring is a flat array of 128-byte CLSAG_GGXXG ring members:
//   [stealth(32) | amount_commitment(32) | blinded_asset_id(32) | concealing(32)]
// Returns 0 on success, 1 on verification failure or deserialisation error.
int cn_zarcanum_verify_full(const uint8_t m[32], const uint8_t kernel_hash[32],
                            const uint8_t *ring, size_t ring_size,
                            const uint8_t last_pow_block_id_hashed[32],
                            const uint8_t stake_ki[32],
                            uint64_t pos_difficulty,
                            const uint8_t *proof, size_t proof_len);

// ── RandomX PoW Hashing ──────────────────────────────────
// key/key_size: RandomX cache key (e.g. "LetheanRandomXv1")
// input/input_size: block header hash (32 bytes) + nonce (8 bytes LE)
// output: 32-byte hash result
// Returns 0 on success.
int bridge_randomx_hash(const uint8_t* key, size_t key_size,
                        const uint8_t* input, size_t input_size,
                        uint8_t* output);

#ifdef __cplusplus
}
#endif
#endif // CRYPTONOTE_BRIDGE_H
