solana_sdk/signer/
mod.rs

1#![cfg(feature = "full")]
2
3use {
4    crate::{
5        pubkey::Pubkey,
6        signature::{PresignerError, Signature},
7        transaction::TransactionError,
8    },
9    itertools::Itertools,
10    thiserror::Error,
11};
12
13pub mod keypair;
14pub mod null_signer;
15pub mod presigner;
16pub mod signers;
17
18#[derive(Debug, Error, PartialEq, Eq)]
19pub enum SignerError {
20    #[error("keypair-pubkey mismatch")]
21    KeypairPubkeyMismatch,
22
23    #[error("not enough signers")]
24    NotEnoughSigners,
25
26    #[error("transaction error")]
27    TransactionError(#[from] TransactionError),
28
29    #[error("custom error: {0}")]
30    Custom(String),
31
32    // Presigner-specific Errors
33    #[error("presigner error")]
34    PresignerError(#[from] PresignerError),
35
36    // Remote Keypair-specific Errors
37    #[error("connection error: {0}")]
38    Connection(String),
39
40    #[error("invalid input: {0}")]
41    InvalidInput(String),
42
43    #[error("no device found")]
44    NoDeviceFound,
45
46    #[error("{0}")]
47    Protocol(String),
48
49    #[error("{0}")]
50    UserCancel(String),
51
52    #[error("too many signers")]
53    TooManySigners,
54}
55
56/// The `Signer` trait declares operations that all digital signature providers
57/// must support. It is the primary interface by which signers are specified in
58/// `Transaction` signing interfaces
59pub trait Signer {
60    /// Infallibly gets the implementor's public key. Returns the all-zeros
61    /// `Pubkey` if the implementor has none.
62    fn pubkey(&self) -> Pubkey {
63        self.try_pubkey().unwrap_or_default()
64    }
65    /// Fallibly gets the implementor's public key
66    fn try_pubkey(&self) -> Result<Pubkey, SignerError>;
67    /// Infallibly produces an Ed25519 signature over the provided `message`
68    /// bytes. Returns the all-zeros `Signature` if signing is not possible.
69    fn sign_message(&self, message: &[u8]) -> Signature {
70        self.try_sign_message(message).unwrap_or_default()
71    }
72    /// Fallibly produces an Ed25519 signature over the provided `message` bytes.
73    fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError>;
74    /// Whether the impelmentation requires user interaction to sign
75    fn is_interactive(&self) -> bool;
76}
77
78impl<T> From<T> for Box<dyn Signer>
79where
80    T: Signer + 'static,
81{
82    fn from(signer: T) -> Self {
83        Box::new(signer)
84    }
85}
86
87impl PartialEq for dyn Signer {
88    fn eq(&self, other: &dyn Signer) -> bool {
89        self.pubkey() == other.pubkey()
90    }
91}
92
93impl std::fmt::Debug for dyn Signer {
94    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
95        write!(fmt, "Signer: {:?}", self.pubkey())
96    }
97}
98
99/// Removes duplicate signers while preserving order. O(n²)
100pub fn unique_signers(signers: Vec<&dyn Signer>) -> Vec<&dyn Signer> {
101    signers.into_iter().unique_by(|s| s.pubkey()).collect()
102}
103
104#[cfg(test)]
105mod tests {
106    use {super::*, crate::signer::keypair::Keypair};
107
108    fn pubkeys(signers: &[&dyn Signer]) -> Vec<Pubkey> {
109        signers.iter().map(|x| x.pubkey()).collect()
110    }
111
112    #[test]
113    fn test_unique_signers() {
114        let alice = Keypair::new();
115        let bob = Keypair::new();
116        assert_eq!(
117            pubkeys(&unique_signers(vec![&alice, &bob, &alice])),
118            pubkeys(&[&alice, &bob])
119        );
120    }
121}