use crate::key_conversion::convert_secret_key;
use crate::key_file::KeyFile;
use crate::{KeyType, PublicKey, SecretKey, Signature};
use near_account_id::AccountId;
use std::fmt::{self, Debug};
use std::io;
use std::path::Path;
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq)]
pub enum Signer {
Empty(EmptySigner),
InMemory(InMemorySigner),
}
impl Signer {
pub fn public_key(&self) -> PublicKey {
match self {
Signer::Empty(signer) => signer.public_key(),
Signer::InMemory(signer) => signer.public_key(),
}
}
pub fn sign(&self, data: &[u8]) -> Signature {
match self {
Signer::Empty(signer) => signer.sign(data),
Signer::InMemory(signer) => signer.sign(data),
}
}
pub fn verify(&self, data: &[u8], signature: &Signature) -> bool {
signature.verify(data, &self.public_key())
}
pub fn compute_vrf_with_proof(&self, data: &[u8]) -> (crate::vrf::Value, crate::vrf::Proof) {
match self {
Signer::Empty(_) => unimplemented!(),
Signer::InMemory(signer) => signer.compute_vrf_with_proof(data),
}
}
pub fn write_to_file(&self, path: &Path) -> io::Result<()> {
match self {
Signer::Empty(_) => unimplemented!(),
Signer::InMemory(signer) => signer.write_to_file(path),
}
}
pub fn get_account_id(&self) -> AccountId {
match self {
Signer::Empty(_) => unimplemented!(),
Signer::InMemory(signer) => signer.account_id.clone(),
}
}
}
impl From<EmptySigner> for Signer {
fn from(signer: EmptySigner) -> Self {
Signer::Empty(signer)
}
}
impl From<InMemorySigner> for Signer {
fn from(signer: InMemorySigner) -> Self {
Signer::InMemory(signer)
}
}
impl From<Signer> for KeyFile {
fn from(signer: Signer) -> KeyFile {
match signer {
Signer::Empty(_) => unimplemented!(),
Signer::InMemory(signer) => KeyFile {
account_id: signer.account_id,
public_key: signer.public_key,
secret_key: signer.secret_key,
},
}
}
}
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq)]
pub struct EmptySigner {}
impl EmptySigner {
pub fn new() -> Self {
Self {}
}
pub fn public_key(&self) -> PublicKey {
PublicKey::empty(KeyType::ED25519)
}
pub fn sign(&self, _data: &[u8]) -> Signature {
Signature::empty(KeyType::ED25519)
}
}
#[derive(Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
pub struct InMemorySigner {
pub account_id: AccountId,
pub public_key: PublicKey,
pub secret_key: SecretKey,
}
impl InMemorySigner {
#[cfg(feature = "rand")]
pub fn from_seed(account_id: AccountId, key_type: KeyType, seed: &str) -> Signer {
let secret_key = SecretKey::from_seed(key_type, seed);
InMemorySigner::from_secret_key(account_id, secret_key)
}
pub fn from_secret_key(account_id: AccountId, secret_key: SecretKey) -> Signer {
Signer::InMemory(Self { account_id, public_key: secret_key.public_key(), secret_key })
}
pub fn from_file(path: &Path) -> io::Result<Signer> {
KeyFile::from_file(path).map(Self::from).map(|s| Signer::InMemory(s))
}
pub fn public_key(&self) -> PublicKey {
self.public_key.clone()
}
pub fn sign(&self, data: &[u8]) -> Signature {
self.secret_key.sign(data)
}
pub fn compute_vrf_with_proof(&self, data: &[u8]) -> (crate::vrf::Value, crate::vrf::Proof) {
let secret_key = convert_secret_key(self.secret_key.unwrap_as_ed25519());
secret_key.compute_vrf_with_proof(&data)
}
pub fn write_to_file(&self, path: &Path) -> io::Result<()> {
KeyFile::from(self).write_to_file(path)
}
#[cfg(feature = "rand")]
pub fn test_signer(account_id: &AccountId) -> Signer {
InMemorySigner::from_seed(account_id.clone(), KeyType::ED25519, account_id.as_ref())
}
}
impl fmt::Debug for InMemorySigner {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"InMemorySigner(account_id: {}, public_key: {})",
self.account_id, self.public_key
)
}
}
impl From<KeyFile> for InMemorySigner {
fn from(key_file: KeyFile) -> Self {
Self {
account_id: key_file.account_id,
public_key: key_file.public_key,
secret_key: key_file.secret_key,
}
}
}
impl From<&InMemorySigner> for KeyFile {
fn from(signer: &InMemorySigner) -> KeyFile {
KeyFile {
account_id: signer.account_id.clone(),
public_key: signer.public_key.clone(),
secret_key: signer.secret_key.clone(),
}
}
}