Skip to main content

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}