sdk: Move `Signer` trait to own module

This commit is contained in:
Trent Nelson 2021-05-07 00:51:52 -06:00 committed by Trent Nelson
parent d4ffd909a4
commit af6f3d776e
3 changed files with 119 additions and 88 deletions

View File

@ -40,6 +40,7 @@ pub mod rpc_port;
pub mod secp256k1_instruction;
pub mod shred_version;
pub mod signature;
pub mod signer;
pub mod signers;
pub mod stake_weighted_timestamp;
pub mod system_transaction;

View File

@ -1,12 +1,11 @@
//! The `signature` module provides functionality for public, and private keys.
#![cfg(feature = "full")]
use crate::{derivation_path::DerivationPath, pubkey::Pubkey, transaction::TransactionError};
use crate::{derivation_path::DerivationPath, pubkey::Pubkey};
use ed25519_dalek::Signer as DalekSigner;
use ed25519_dalek_bip32::Error as Bip32Error;
use generic_array::{typenum::U64, GenericArray};
use hmac::Hmac;
use itertools::Itertools;
use rand::{rngs::OsRng, CryptoRng, RngCore};
use std::{
borrow::{Borrow, Cow},
@ -20,6 +19,9 @@ use std::{
};
use thiserror::Error;
// legacy module paths
pub use crate::signer::*;
#[derive(Debug)]
pub struct Keypair(ed25519_dalek::Keypair);
@ -158,34 +160,6 @@ impl FromStr for Signature {
}
}
pub trait Signer {
fn pubkey(&self) -> Pubkey {
self.try_pubkey().unwrap_or_default()
}
fn try_pubkey(&self) -> Result<Pubkey, SignerError>;
fn sign_message(&self, message: &[u8]) -> Signature {
self.try_sign_message(message).unwrap_or_default()
}
fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError>;
}
impl PartialEq for dyn Signer {
fn eq(&self, other: &dyn Signer) -> bool {
self.pubkey() == other.pubkey()
}
}
impl std::fmt::Debug for dyn Signer {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(fmt, "Signer: {:?}", self.pubkey())
}
}
/// Remove duplicates signers while preserving order. O(n²)
pub fn unique_signers(signers: Vec<&dyn Signer>) -> Vec<&dyn Signer> {
signers.into_iter().unique_by(|s| s.pubkey()).collect()
}
impl Signer for Keypair {
/// Return the public key for the given keypair
fn pubkey(&self) -> Pubkey {
@ -214,50 +188,6 @@ where
}
}
impl<T> From<T> for Box<dyn Signer>
where
T: Signer + 'static,
{
fn from(signer: T) -> Self {
Box::new(signer)
}
}
#[derive(Debug, Error, PartialEq)]
pub enum SignerError {
#[error("keypair-pubkey mismatch")]
KeypairPubkeyMismatch,
#[error("not enough signers")]
NotEnoughSigners,
#[error("transaction error")]
TransactionError(#[from] TransactionError),
#[error("custom error: {0}")]
Custom(String),
// Presigner-specific Errors
#[error("presigner error")]
PresignerError(#[from] PresignerError),
// Remote Keypair-specific Errors
#[error("connection error: {0}")]
Connection(String),
#[error("invalid input: {0}")]
InvalidInput(String),
#[error("no device found")]
NoDeviceFound,
#[error("{0}")]
Protocol(String),
#[error("{0}")]
UserCancel(String),
}
#[derive(Clone, Debug, Default)]
pub struct Presigner {
pubkey: Pubkey,
@ -629,20 +559,6 @@ mod tests {
assert_eq!(presigner, presigner2);
}
fn pubkeys(signers: &[&dyn Signer]) -> Vec<Pubkey> {
signers.iter().map(|x| x.pubkey()).collect()
}
#[test]
fn test_unique_signers() {
let alice = Keypair::new();
let bob = Keypair::new();
assert_eq!(
pubkeys(&unique_signers(vec![&alice, &bob, &alice])),
pubkeys(&[&alice, &bob])
);
}
#[test]
fn test_off_curve_pubkey_verify_fails() {
// Golden point off the ed25519 curve

114
sdk/src/signer/mod.rs Normal file
View File

@ -0,0 +1,114 @@
#![cfg(feature = "full")]
use {
crate::{
pubkey::Pubkey,
signature::{PresignerError, Signature},
transaction::TransactionError,
},
itertools::Itertools,
thiserror::Error,
};
pub mod keypair;
#[derive(Debug, Error, PartialEq)]
pub enum SignerError {
#[error("keypair-pubkey mismatch")]
KeypairPubkeyMismatch,
#[error("not enough signers")]
NotEnoughSigners,
#[error("transaction error")]
TransactionError(#[from] TransactionError),
#[error("custom error: {0}")]
Custom(String),
// Presigner-specific Errors
#[error("presigner error")]
PresignerError(#[from] PresignerError),
// Remote Keypair-specific Errors
#[error("connection error: {0}")]
Connection(String),
#[error("invalid input: {0}")]
InvalidInput(String),
#[error("no device found")]
NoDeviceFound,
#[error("{0}")]
Protocol(String),
#[error("{0}")]
UserCancel(String),
}
/// The `Signer` trait declares operations that all digital signature providers
/// must support. It is the primary interface by which signers are specified in
/// `Transaction` signing interfaces
pub trait Signer {
/// Infallibly gets the implementor's public key. Returns the all-zeros
/// `Pubkey` if the implementor has none.
fn pubkey(&self) -> Pubkey {
self.try_pubkey().unwrap_or_default()
}
/// Fallibly gets the implementor's public key
fn try_pubkey(&self) -> Result<Pubkey, SignerError>;
/// Invallibly produces an Ed25519 signature over the provided `message`
/// bytes. Returns the all-zeros `Signature` if signing is not possible.
fn sign_message(&self, message: &[u8]) -> Signature {
self.try_sign_message(message).unwrap_or_default()
}
/// Fallibly produces an Ed25519 signature over the provided `message` bytes.
fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError>;
}
impl<T> From<T> for Box<dyn Signer>
where
T: Signer + 'static,
{
fn from(signer: T) -> Self {
Box::new(signer)
}
}
impl PartialEq for dyn Signer {
fn eq(&self, other: &dyn Signer) -> bool {
self.pubkey() == other.pubkey()
}
}
impl std::fmt::Debug for dyn Signer {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(fmt, "Signer: {:?}", self.pubkey())
}
}
/// Removes duplicate signers while preserving order. O(n²)
pub fn unique_signers(signers: Vec<&dyn Signer>) -> Vec<&dyn Signer> {
signers.into_iter().unique_by(|s| s.pubkey()).collect()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::signer::keypair::Keypair;
fn pubkeys(signers: &[&dyn Signer]) -> Vec<Pubkey> {
signers.iter().map(|x| x.pubkey()).collect()
}
#[test]
fn test_unique_signers() {
let alice = Keypair::new();
let bob = Keypair::new();
assert_eq!(
pubkeys(&unique_signers(vec![&alice, &bob, &alice])),
pubkeys(&[&alice, &bob])
);
}
}