diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 64f89324ee..897a1db49b 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -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; diff --git a/sdk/src/signature.rs b/sdk/src/signature.rs index 8102b9582a..d91a8ba2b6 100644 --- a/sdk/src/signature.rs +++ b/sdk/src/signature.rs @@ -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; - fn sign_message(&self, message: &[u8]) -> Signature { - self.try_sign_message(message).unwrap_or_default() - } - fn try_sign_message(&self, message: &[u8]) -> Result; -} - -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 From for Box -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 { - 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 diff --git a/sdk/src/signer/mod.rs b/sdk/src/signer/mod.rs new file mode 100644 index 0000000000..dc81d8257f --- /dev/null +++ b/sdk/src/signer/mod.rs @@ -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; + /// 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; +} + +impl From for Box +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 { + 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]) + ); + } +}