mina_signer/lib.rs
1#![deny(missing_docs)]
2#![doc = include_str!("../README.md")]
3#![no_std]
4
5extern crate alloc;
6
7use alloc::{
8 string::{String, ToString},
9 vec,
10 vec::Vec,
11};
12use ark_ec::AffineRepr;
13use core::cmp::{Eq, PartialEq};
14pub use keypair::Keypair;
15pub use mina_curves::pasta::Pallas as CurvePoint;
16use mina_hasher::{DomainParameter, Hashable};
17pub use pubkey::{CompressedPubKey, PubKey};
18pub use schnorr::Schnorr;
19pub use seckey::SecKey;
20use serde::{Deserialize, Serialize};
21pub use signature::Signature;
22
23pub mod keypair;
24pub mod pubkey;
25pub mod schnorr;
26pub mod seckey;
27pub mod signature;
28
29/// Base field element type
30pub type BaseField = <CurvePoint as AffineRepr>::BaseField;
31
32/// Scalar field element type
33pub type ScalarField = <CurvePoint as AffineRepr>::ScalarField;
34
35/// Mina network (or blockchain) identifier
36#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
37pub enum NetworkId {
38 /// Id for all testnets
39 TESTNET = 0x00,
40
41 /// Id for mainnet
42 MAINNET = 0x01,
43}
44
45impl From<NetworkId> for u8 {
46 fn from(id: NetworkId) -> u8 {
47 id as u8
48 }
49}
50
51impl NetworkId {
52 /// Convert the network ID to its domain string representation for
53 /// cryptographic hashing.
54 ///
55 /// This is used in the `Hashable` trait's `domain_string` method to provide
56 /// domain separation for signature hashing.
57 ///
58 /// Returns:
59 /// - `"MinaSignatureMainnet"` for `NetworkId::MAINNET`
60 /// - `"CodaSignature"` for `NetworkId::TESTNET`
61 pub fn into_domain_string(self) -> String {
62 match self {
63 NetworkId::MAINNET => "MinaSignatureMainnet".to_string(),
64 NetworkId::TESTNET => "CodaSignature".to_string(),
65 }
66 }
67}
68
69impl DomainParameter for NetworkId {
70 fn into_bytes(self) -> Vec<u8> {
71 vec![self as u8]
72 }
73}
74
75/// Interface for signed objects
76///
77/// Signer interface for signing [`Hashable`] inputs and verifying
78/// [`Signatures`](Signature) using [`Keypairs`](Keypair) and
79/// [`PubKeys`](PubKey)
80pub trait Signer<H: Hashable> {
81 /// Sign `input` (see [`Hashable`]) using keypair `kp` and return the
82 /// corresponding signature.
83 ///
84 /// # Parameters
85 ///
86 /// * `kp` - The keypair to use for signing
87 /// * `input` - The message to sign (must implement [`Hashable`])
88 /// * `packed` - Controls nonce derivation method:
89 /// - `true`: Use OCaml/TypeScript compatible nonce derivation with field
90 /// packing
91 /// - `false`: Use standard Rust nonce derivation
92 ///
93 /// # Returns
94 ///
95 /// A [`Signature`] over the input message.
96 ///
97 /// # Compatibility
98 ///
99 /// Use `packed: true` when compatibility with OCaml and TypeScript
100 /// implementations is required. Use `packed: false` for standard Rust-only
101 /// usage.
102 ///
103 /// **Note**: The standard nonce derivation (`packed: false`) will be
104 /// deprecated in future versions. Use `packed: true` for new code to ensure
105 /// forward compatibility.
106 fn sign(&mut self, kp: &Keypair, input: &H, packed: bool) -> Signature;
107
108 /// Verify that the signature `sig` on `input` (see [`Hashable`]) is signed
109 /// with the secret key corresponding to `pub_key`.
110 /// Return `true` if the signature is valid and `false` otherwise.
111 fn verify(&mut self, sig: &Signature, pub_key: &PubKey, input: &H) -> bool;
112}
113
114/// Create a legacy signer context with domain parameters initialized with
115/// `domain_param`
116///
117/// **Example**
118///
119/// ```
120/// #[path = "../tests/transaction.rs"]
121/// mod transaction;
122/// use mina_signer::{NetworkId, self, Signer};
123/// use transaction::Transaction;
124///
125/// let mut ctx = mina_signer::create_legacy::<Transaction>(NetworkId::TESTNET);
126/// ```
127pub fn create_legacy<H: 'static + Hashable>(domain_param: H::D) -> impl Signer<H> {
128 schnorr::create_legacy::<H>(domain_param)
129}
130
131/// Create a kimchi signer context for ZkApp signing (Berkeley upgrade)
132/// with domain parameters initialized with `domain_param`
133///
134/// **Example**
135///
136/// ```
137/// #[path = "../tests/transaction.rs"]
138/// mod transaction;
139/// use mina_signer::{NetworkId, self, Signer};
140/// use transaction::Transaction;
141///
142/// let mut ctx = mina_signer::create_kimchi::<Transaction>(NetworkId::TESTNET);
143/// ```
144pub fn create_kimchi<H: 'static + Hashable>(domain_param: H::D) -> impl Signer<H> {
145 schnorr::create_kimchi::<H>(domain_param)
146}