1use crate::key_conversion::convert_secret_key;
2use crate::key_file::KeyFile;
3use crate::{KeyType, PublicKey, SecretKey, Signature};
4use near_account_id::AccountId;
5use std::fmt::{self, Debug};
6use std::io;
7use std::path::Path;
8
9#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq)]
11pub enum Signer {
12 Empty(EmptySigner),
14 InMemory(InMemorySigner),
16}
17
18impl Signer {
20 pub fn public_key(&self) -> PublicKey {
21 match self {
22 Signer::Empty(signer) => signer.public_key(),
23 Signer::InMemory(signer) => signer.public_key(),
24 }
25 }
26
27 pub fn sign(&self, data: &[u8]) -> Signature {
28 match self {
29 Signer::Empty(signer) => signer.sign(data),
30 Signer::InMemory(signer) => signer.sign(data),
31 }
32 }
33
34 pub fn verify(&self, data: &[u8], signature: &Signature) -> bool {
35 signature.verify(data, &self.public_key())
36 }
37
38 pub fn compute_vrf_with_proof(&self, data: &[u8]) -> (crate::vrf::Value, crate::vrf::Proof) {
39 match self {
40 Signer::Empty(_) => unimplemented!(),
41 Signer::InMemory(signer) => signer.compute_vrf_with_proof(data),
42 }
43 }
44
45 pub fn write_to_file(&self, path: &Path) -> io::Result<()> {
47 match self {
48 Signer::Empty(_) => unimplemented!(),
49 Signer::InMemory(signer) => signer.write_to_file(path),
50 }
51 }
52
53 pub fn get_account_id(&self) -> AccountId {
54 match self {
55 Signer::Empty(_) => unimplemented!(),
56 Signer::InMemory(signer) => signer.account_id.clone(),
57 }
58 }
59}
60
61impl From<EmptySigner> for Signer {
62 fn from(signer: EmptySigner) -> Self {
63 Signer::Empty(signer)
64 }
65}
66
67impl From<InMemorySigner> for Signer {
68 fn from(signer: InMemorySigner) -> Self {
69 Signer::InMemory(signer)
70 }
71}
72
73impl From<Signer> for KeyFile {
74 fn from(signer: Signer) -> KeyFile {
75 match signer {
76 Signer::Empty(_) => unimplemented!(),
77 Signer::InMemory(signer) => KeyFile {
78 account_id: signer.account_id,
79 public_key: signer.public_key,
80 secret_key: signer.secret_key,
81 },
82 }
83 }
84}
85
86#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq)]
88pub struct EmptySigner {}
89
90impl EmptySigner {
91 pub fn new() -> Self {
92 Self {}
93 }
94
95 pub fn public_key(&self) -> PublicKey {
96 PublicKey::empty(KeyType::ED25519)
97 }
98
99 pub fn sign(&self, _data: &[u8]) -> Signature {
100 Signature::empty(KeyType::ED25519)
101 }
102}
103
104#[derive(Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
106pub struct InMemorySigner {
107 pub account_id: AccountId,
108 pub public_key: PublicKey,
109 pub secret_key: SecretKey,
110}
111
112impl InMemorySigner {
113 #[cfg(feature = "rand")]
114 pub fn from_seed(account_id: AccountId, key_type: KeyType, seed: &str) -> Signer {
115 let secret_key = SecretKey::from_seed(key_type, seed);
116 InMemorySigner::from_secret_key(account_id, secret_key)
117 }
118
119 pub fn from_secret_key(account_id: AccountId, secret_key: SecretKey) -> Signer {
120 Signer::InMemory(Self { account_id, public_key: secret_key.public_key(), secret_key })
121 }
122
123 pub fn from_file(path: &Path) -> io::Result<Signer> {
124 KeyFile::from_file(path).map(Self::from).map(|s| Signer::InMemory(s))
125 }
126
127 pub fn public_key(&self) -> PublicKey {
128 self.public_key.clone()
129 }
130
131 pub fn sign(&self, data: &[u8]) -> Signature {
132 self.secret_key.sign(data)
133 }
134
135 pub fn compute_vrf_with_proof(&self, data: &[u8]) -> (crate::vrf::Value, crate::vrf::Proof) {
136 let secret_key = convert_secret_key(self.secret_key.unwrap_as_ed25519());
137 secret_key.compute_vrf_with_proof(&data)
138 }
139
140 pub fn write_to_file(&self, path: &Path) -> io::Result<()> {
141 KeyFile::from(self).write_to_file(path)
142 }
143
144 #[cfg(feature = "rand")]
145 pub fn test_signer(account_id: &AccountId) -> Signer {
146 InMemorySigner::from_seed(account_id.clone(), KeyType::ED25519, account_id.as_ref())
147 }
148}
149
150impl fmt::Debug for InMemorySigner {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 write!(
153 f,
154 "InMemorySigner(account_id: {}, public_key: {})",
155 self.account_id, self.public_key
156 )
157 }
158}
159
160impl From<KeyFile> for InMemorySigner {
161 fn from(key_file: KeyFile) -> Self {
162 Self {
163 account_id: key_file.account_id,
164 public_key: key_file.public_key,
165 secret_key: key_file.secret_key,
166 }
167 }
168}
169
170impl From<&InMemorySigner> for KeyFile {
171 fn from(signer: &InMemorySigner) -> KeyFile {
172 KeyFile {
173 account_id: signer.account_id.clone(),
174 public_key: signer.public_key.clone(),
175 secret_key: signer.secret_key.clone(),
176 }
177 }
178}