Skip to main content

cdk_signatory/
signatory.rs

1//! Signatory mod
2//!
3//! This module abstract all the key related operations, defining an interface for the necessary
4//! operations, to be implemented by the different signatory implementations.
5//!
6//! There is an in memory implementation, when the keys are stored in memory, in the same process,
7//! but it is isolated from the rest of the application, and they communicate through a channel with
8//! the defined API.
9use cdk_common::common::IssuerVersion;
10use cdk_common::error::Error;
11use cdk_common::mint::MintKeySetInfo;
12use cdk_common::{
13    BlindSignature, BlindedMessage, CurrencyUnit, Id, KeySet, Keys, MintKeySet, Proof, PublicKey,
14};
15
16#[derive(Debug)]
17/// Type alias to make the keyset info API more useful, queryable by unit and Id
18pub enum KeysetIdentifier {
19    /// Mint Keyset by unit
20    Unit(CurrencyUnit),
21    /// Mint Keyset by Id
22    Id(Id),
23}
24
25impl From<Id> for KeysetIdentifier {
26    fn from(id: Id) -> Self {
27        Self::Id(id)
28    }
29}
30
31impl From<CurrencyUnit> for KeysetIdentifier {
32    fn from(unit: CurrencyUnit) -> Self {
33        Self::Unit(unit)
34    }
35}
36
37/// RotateKeyArguments
38///
39/// This struct is used to pass the arguments to the rotate_keyset function
40///
41/// TODO: Change argument to accept a vector of Amount instead of max_order.
42#[derive(Debug, Clone)]
43pub struct RotateKeyArguments {
44    /// Unit
45    pub unit: CurrencyUnit,
46    /// List of amounts to support
47    pub amounts: Vec<u64>,
48    /// Input fee
49    pub input_fee_ppk: u64,
50    /// KeySet Version
51    pub use_keyset_v2: bool,
52}
53
54#[derive(Debug, Clone)]
55/// Signatory keysets
56pub struct SignatoryKeysets {
57    /// The public key
58    pub pubkey: PublicKey,
59    /// The list of keysets
60    pub keysets: Vec<SignatoryKeySet>,
61}
62
63#[derive(Debug, Clone)]
64/// SignatoryKeySet
65///
66/// This struct is used to represent a keyset and its info, pretty much all the information but the
67/// private key, that will never leave the signatory
68pub struct SignatoryKeySet {
69    /// The keyset Id
70    pub id: Id,
71    /// The Currency Unit
72    pub unit: CurrencyUnit,
73    /// Whether to set it as active or not
74    pub active: bool,
75    /// The list of public keys
76    pub keys: Keys,
77    /// Amounts supported by the keyset
78    pub amounts: Vec<u64>,
79    /// Input fee for the keyset (parts per thousand)
80    pub input_fee_ppk: u64,
81    /// Final expiry of the keyset (unix timestamp in the future)
82    pub final_expiry: Option<u64>,
83    /// Issuer Version
84    pub issuer_version: Option<IssuerVersion>,
85}
86
87impl From<&SignatoryKeySet> for KeySet {
88    fn from(val: &SignatoryKeySet) -> Self {
89        val.to_owned().into()
90    }
91}
92
93impl From<SignatoryKeySet> for KeySet {
94    fn from(val: SignatoryKeySet) -> Self {
95        KeySet {
96            id: val.id,
97            unit: val.unit,
98            active: Some(val.active),
99            keys: val.keys,
100            input_fee_ppk: val.input_fee_ppk,
101            final_expiry: val.final_expiry,
102        }
103    }
104}
105
106impl From<&SignatoryKeySet> for MintKeySetInfo {
107    fn from(val: &SignatoryKeySet) -> Self {
108        val.to_owned().into()
109    }
110}
111
112impl From<SignatoryKeySet> for MintKeySetInfo {
113    fn from(val: SignatoryKeySet) -> Self {
114        MintKeySetInfo {
115            id: val.id,
116            unit: val.unit,
117            active: val.active,
118            input_fee_ppk: val.input_fee_ppk,
119            derivation_path: Default::default(),
120            derivation_path_index: Default::default(),
121            amounts: val.amounts,
122            final_expiry: val.final_expiry,
123            issuer_version: val.issuer_version,
124            valid_from: 0,
125        }
126    }
127}
128
129impl From<&(MintKeySetInfo, MintKeySet)> for SignatoryKeySet {
130    fn from((info, key): &(MintKeySetInfo, MintKeySet)) -> Self {
131        Self {
132            id: info.id,
133            unit: key.unit.clone(),
134            active: info.active,
135            input_fee_ppk: info.input_fee_ppk,
136            amounts: info.amounts.clone(),
137            keys: key.keys.clone().into(),
138            final_expiry: key.final_expiry,
139            issuer_version: info.issuer_version.clone(),
140        }
141    }
142}
143
144#[async_trait::async_trait]
145/// Signatory trait
146pub trait Signatory {
147    /// The Signatory implementation name. This may be exposed, so being as discrete as possible is
148    /// advised.
149    fn name(&self) -> String;
150
151    /// Blind sign a message.
152    ///
153    /// The message can be for a coin or an auth token.
154    async fn blind_sign(
155        &self,
156        blinded_messages: Vec<BlindedMessage>,
157    ) -> Result<Vec<BlindSignature>, Error>;
158
159    /// Verify [`Proof`] meets conditions and is signed by the mint (ignores P2PK/HTLC signatures"
160    async fn verify_proofs(&self, proofs: Vec<Proof>) -> Result<(), Error>;
161
162    /// Retrieve the list of all mint keysets
163    async fn keysets(&self) -> Result<SignatoryKeysets, Error>;
164
165    /// Add current keyset to inactive keysets
166    /// Generate new keyset
167    async fn rotate_keyset(&self, args: RotateKeyArguments) -> Result<SignatoryKeySet, Error>;
168}