solana_sdk/signer/
signers.rs

1#![cfg(feature = "full")]
2
3use {
4    crate::{
5        pubkey::Pubkey,
6        signature::{Signature, Signer, SignerError},
7    },
8    std::sync::Arc,
9};
10
11/// Convenience trait for working with mixed collections of `Signer`s
12pub trait Signers {
13    fn pubkeys(&self) -> Vec<Pubkey>;
14    fn try_pubkeys(&self) -> Result<Vec<Pubkey>, SignerError>;
15    fn sign_message(&self, message: &[u8]) -> Vec<Signature>;
16    fn try_sign_message(&self, message: &[u8]) -> Result<Vec<Signature>, SignerError>;
17    fn is_interactive(&self) -> bool;
18}
19
20macro_rules! default_keypairs_impl {
21    () => {
22        fn pubkeys(&self) -> Vec<Pubkey> {
23            self.iter().map(|keypair| keypair.pubkey()).collect()
24        }
25
26        fn try_pubkeys(&self) -> Result<Vec<Pubkey>, SignerError> {
27            let mut pubkeys = Vec::new();
28            for keypair in self.iter() {
29                pubkeys.push(keypair.try_pubkey()?);
30            }
31            Ok(pubkeys)
32        }
33
34        fn sign_message(&self, message: &[u8]) -> Vec<Signature> {
35            self.iter()
36                .map(|keypair| keypair.sign_message(message))
37                .collect()
38        }
39
40        fn try_sign_message(&self, message: &[u8]) -> Result<Vec<Signature>, SignerError> {
41            let mut signatures = Vec::new();
42            for keypair in self.iter() {
43                signatures.push(keypair.try_sign_message(message)?);
44            }
45            Ok(signatures)
46        }
47
48        fn is_interactive(&self) -> bool {
49            self.iter().any(|s| s.is_interactive())
50        }
51    };
52}
53
54impl<T: Signer> Signers for [&T] {
55    default_keypairs_impl!();
56}
57
58impl Signers for [Box<dyn Signer>] {
59    default_keypairs_impl!();
60}
61
62impl Signers for Vec<Box<dyn Signer>> {
63    default_keypairs_impl!();
64}
65
66impl Signers for [Arc<dyn Signer>] {
67    default_keypairs_impl!();
68}
69
70impl Signers for Vec<Arc<dyn Signer>> {
71    default_keypairs_impl!();
72}
73
74impl Signers for Vec<&dyn Signer> {
75    default_keypairs_impl!();
76}
77
78impl Signers for [&dyn Signer] {
79    default_keypairs_impl!();
80}
81
82impl Signers for [&dyn Signer; 0] {
83    default_keypairs_impl!();
84}
85
86impl Signers for [&dyn Signer; 1] {
87    default_keypairs_impl!();
88}
89
90impl Signers for [&dyn Signer; 2] {
91    default_keypairs_impl!();
92}
93
94impl Signers for [&dyn Signer; 3] {
95    default_keypairs_impl!();
96}
97
98impl Signers for [&dyn Signer; 4] {
99    default_keypairs_impl!();
100}
101
102impl<T: Signer> Signers for [&T; 0] {
103    default_keypairs_impl!();
104}
105
106impl<T: Signer> Signers for [&T; 1] {
107    default_keypairs_impl!();
108}
109
110impl<T: Signer> Signers for [&T; 2] {
111    default_keypairs_impl!();
112}
113
114impl<T: Signer> Signers for [&T; 3] {
115    default_keypairs_impl!();
116}
117
118impl<T: Signer> Signers for [&T; 4] {
119    default_keypairs_impl!();
120}
121
122impl<T: Signer> Signers for Vec<&T> {
123    default_keypairs_impl!();
124}
125
126#[cfg(test)]
127mod tests {
128    use super::*;
129
130    struct Foo;
131    impl Signer for Foo {
132        fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
133            Ok(Pubkey::default())
134        }
135        fn try_sign_message(&self, _message: &[u8]) -> Result<Signature, SignerError> {
136            Ok(Signature::default())
137        }
138        fn is_interactive(&self) -> bool {
139            false
140        }
141    }
142
143    struct Bar;
144    impl Signer for Bar {
145        fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
146            Ok(Pubkey::default())
147        }
148        fn try_sign_message(&self, _message: &[u8]) -> Result<Signature, SignerError> {
149            Ok(Signature::default())
150        }
151        fn is_interactive(&self) -> bool {
152            false
153        }
154    }
155
156    #[test]
157    fn test_dyn_keypairs_compile() {
158        let xs: Vec<Box<dyn Signer>> = vec![Box::new(Foo {}), Box::new(Bar {})];
159        assert_eq!(
160            xs.sign_message(b""),
161            vec![Signature::default(), Signature::default()],
162        );
163
164        // Same as above, but less compiler magic.
165        let xs_ref: &[Box<dyn Signer>] = &xs;
166        assert_eq!(
167            Signers::sign_message(xs_ref, b""),
168            vec![Signature::default(), Signature::default()],
169        );
170    }
171
172    #[test]
173    fn test_dyn_keypairs_by_ref_compile() {
174        let foo = Foo {};
175        let bar = Bar {};
176        let xs: Vec<&dyn Signer> = vec![&foo, &bar];
177        assert_eq!(
178            xs.sign_message(b""),
179            vec![Signature::default(), Signature::default()],
180        );
181
182        // Same as above, but less compiler magic.
183        let xs_ref: &[&dyn Signer] = &xs;
184        assert_eq!(
185            Signers::sign_message(xs_ref, b""),
186            vec![Signature::default(), Signature::default()],
187        );
188    }
189}