solana_sdk/signer/
mod.rs

1//! Abstractions and implementations for transaction signers.
2
3#![cfg(feature = "full")]
4
5use {
6    crate::{
7        pubkey::Pubkey,
8        signature::{PresignerError, Signature},
9    },
10    itertools::Itertools,
11    solana_derivation_path::DerivationPath,
12    solana_transaction_error::TransactionError,
13    std::{
14        error,
15        fs::{self, File, OpenOptions},
16        io::{Read, Write},
17        ops::Deref,
18        path::Path,
19    },
20    thiserror::Error,
21};
22
23pub mod keypair;
24pub mod null_signer;
25pub mod presigner;
26pub mod signers;
27
28#[derive(Debug, Error, PartialEq, Eq)]
29pub enum SignerError {
30    #[error("keypair-pubkey mismatch")]
31    KeypairPubkeyMismatch,
32
33    #[error("not enough signers")]
34    NotEnoughSigners,
35
36    #[error("transaction error")]
37    TransactionError(#[from] TransactionError),
38
39    #[error("custom error: {0}")]
40    Custom(String),
41
42    // Presigner-specific Errors
43    #[error("presigner error")]
44    PresignerError(#[from] PresignerError),
45
46    // Remote Keypair-specific Errors
47    #[error("connection error: {0}")]
48    Connection(String),
49
50    #[error("invalid input: {0}")]
51    InvalidInput(String),
52
53    #[error("no device found")]
54    NoDeviceFound,
55
56    #[error("{0}")]
57    Protocol(String),
58
59    #[error("{0}")]
60    UserCancel(String),
61
62    #[error("too many signers")]
63    TooManySigners,
64}
65
66/// The `Signer` trait declares operations that all digital signature providers
67/// must support. It is the primary interface by which signers are specified in
68/// `Transaction` signing interfaces
69pub trait Signer {
70    /// Infallibly gets the implementor's public key. Returns the all-zeros
71    /// `Pubkey` if the implementor has none.
72    fn pubkey(&self) -> Pubkey {
73        self.try_pubkey().unwrap_or_default()
74    }
75    /// Fallibly gets the implementor's public key
76    fn try_pubkey(&self) -> Result<Pubkey, SignerError>;
77    /// Infallibly produces an Ed25519 signature over the provided `message`
78    /// bytes. Returns the all-zeros `Signature` if signing is not possible.
79    fn sign_message(&self, message: &[u8]) -> Signature {
80        self.try_sign_message(message).unwrap_or_default()
81    }
82    /// Fallibly produces an Ed25519 signature over the provided `message` bytes.
83    fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError>;
84    /// Whether the implementation requires user interaction to sign
85    fn is_interactive(&self) -> bool;
86}
87
88/// This implements `Signer` for all ptr types - `Box/Rc/Arc/&/&mut` etc
89impl<Container: Deref<Target = impl Signer + ?Sized>> Signer for Container {
90    #[inline]
91    fn pubkey(&self) -> Pubkey {
92        self.deref().pubkey()
93    }
94
95    fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
96        self.deref().try_pubkey()
97    }
98
99    fn sign_message(&self, message: &[u8]) -> Signature {
100        self.deref().sign_message(message)
101    }
102
103    fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError> {
104        self.deref().try_sign_message(message)
105    }
106
107    fn is_interactive(&self) -> bool {
108        self.deref().is_interactive()
109    }
110}
111
112impl PartialEq for dyn Signer {
113    fn eq(&self, other: &dyn Signer) -> bool {
114        self.pubkey() == other.pubkey()
115    }
116}
117
118impl Eq for dyn Signer {}
119
120impl std::fmt::Debug for dyn Signer {
121    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
122        write!(fmt, "Signer: {:?}", self.pubkey())
123    }
124}
125
126/// Removes duplicate signers while preserving order. O(n²)
127pub fn unique_signers(signers: Vec<&dyn Signer>) -> Vec<&dyn Signer> {
128    signers.into_iter().unique_by(|s| s.pubkey()).collect()
129}
130
131/// The `EncodableKey` trait defines the interface by which cryptographic keys/keypairs are read,
132/// written, and derived from sources.
133pub trait EncodableKey: Sized {
134    fn read<R: Read>(reader: &mut R) -> Result<Self, Box<dyn error::Error>>;
135    fn read_from_file<F: AsRef<Path>>(path: F) -> Result<Self, Box<dyn error::Error>> {
136        let mut file = File::open(path.as_ref())?;
137        Self::read(&mut file)
138    }
139    fn write<W: Write>(&self, writer: &mut W) -> Result<String, Box<dyn error::Error>>;
140    fn write_to_file<F: AsRef<Path>>(&self, outfile: F) -> Result<String, Box<dyn error::Error>> {
141        let outfile = outfile.as_ref();
142
143        if let Some(outdir) = outfile.parent() {
144            fs::create_dir_all(outdir)?;
145        }
146
147        let mut f = {
148            #[cfg(not(unix))]
149            {
150                OpenOptions::new()
151            }
152            #[cfg(unix)]
153            {
154                use std::os::unix::fs::OpenOptionsExt;
155                OpenOptions::new().mode(0o600)
156            }
157        }
158        .write(true)
159        .truncate(true)
160        .create(true)
161        .open(outfile)?;
162
163        self.write(&mut f)
164    }
165}
166
167/// The `SeedDerivable` trait defines the interface by which cryptographic keys/keypairs are
168/// derived from byte seeds, derivation paths, and passphrases.
169pub trait SeedDerivable: Sized {
170    fn from_seed(seed: &[u8]) -> Result<Self, Box<dyn error::Error>>;
171    fn from_seed_and_derivation_path(
172        seed: &[u8],
173        derivation_path: Option<DerivationPath>,
174    ) -> Result<Self, Box<dyn error::Error>>;
175    fn from_seed_phrase_and_passphrase(
176        seed_phrase: &str,
177        passphrase: &str,
178    ) -> Result<Self, Box<dyn error::Error>>;
179}
180
181/// The `EncodableKeypair` trait extends `EncodableKey` for asymmetric keypairs, i.e. have
182/// associated public keys.
183pub trait EncodableKeypair: EncodableKey {
184    type Pubkey: ToString;
185
186    /// Returns an encodable representation of the associated public key.
187    fn encodable_pubkey(&self) -> Self::Pubkey;
188}
189
190#[cfg(test)]
191mod tests {
192    use {super::*, crate::signer::keypair::Keypair};
193
194    fn pubkeys(signers: &[&dyn Signer]) -> Vec<Pubkey> {
195        signers.iter().map(|x| x.pubkey()).collect()
196    }
197
198    #[test]
199    fn test_unique_signers() {
200        let alice = Keypair::new();
201        let bob = Keypair::new();
202        assert_eq!(
203            pubkeys(&unique_signers(vec![&alice, &bob, &alice])),
204            pubkeys(&[&alice, &bob])
205        );
206    }
207
208    #[test]
209    fn test_containers() {
210        use std::{rc::Rc, sync::Arc};
211
212        struct Foo<S: Signer> {
213            #[allow(unused)]
214            signer: S,
215        }
216
217        fn foo(_s: impl Signer) {}
218
219        let _arc_signer = Foo {
220            signer: Arc::new(Keypair::new()),
221        };
222        foo(Arc::new(Keypair::new()));
223
224        let _rc_signer = Foo {
225            signer: Rc::new(Keypair::new()),
226        };
227        foo(Rc::new(Keypair::new()));
228
229        let _ref_signer = Foo {
230            signer: &Keypair::new(),
231        };
232        foo(Keypair::new());
233
234        let _box_signer = Foo {
235            signer: Box::new(Keypair::new()),
236        };
237        foo(Box::new(Keypair::new()));
238
239        let _signer = Foo {
240            signer: Keypair::new(),
241        };
242        foo(Keypair::new());
243    }
244}