diff --git a/clap-v3-utils/src/keypair.rs b/clap-v3-utils/src/keypair.rs index bbec1a672..7c905f4c3 100644 --- a/clap-v3-utils/src/keypair.rs +++ b/clap-v3-utils/src/keypair.rs @@ -30,7 +30,7 @@ use { pubkey::Pubkey, signature::{ generate_seed_from_seed_phrase_and_passphrase, read_keypair, read_keypair_file, - EncodableKey, Keypair, NullSigner, Presigner, Signature, Signer, + EncodableKey, EncodableKeypair, Keypair, NullSigner, Presigner, Signature, Signer, }, }, solana_zk_token_sdk::encryption::{auth_encryption::AeKey, elgamal::ElGamalKeypair}, @@ -1004,23 +1004,11 @@ pub fn keypair_from_path( ) -> Result> { let keypair = encodable_key_from_path(matches, path, keypair_name)?; if confirm_pubkey { - confirm_keypair_pubkey(&keypair); + confirm_encodable_keypair_pubkey(&keypair, "pubkey"); } Ok(keypair) } -fn confirm_keypair_pubkey(keypair: &Keypair) { - let pubkey = keypair.pubkey(); - print!("Recovered pubkey `{pubkey:?}`. Continue? (y/n): "); - let _ignored = stdout().flush(); - let mut input = String::new(); - stdin().read_line(&mut input).expect("Unexpected input"); - if input.to_lowercase().trim() != "y" { - println!("Exiting"); - exit(1); - } -} - /// Loads an [ElGamalKeypair] from one of several possible sources. /// /// If `confirm_pubkey` is `true` then after deriving the keypair, the user will @@ -1063,14 +1051,14 @@ pub fn elgamal_keypair_from_path( ) -> Result> { let elgamal_keypair = encodable_key_from_path(matches, path, elgamal_keypair_name)?; if confirm_pubkey { - confirm_elgamal_keypair_pubkey(&elgamal_keypair); + confirm_encodable_keypair_pubkey(&elgamal_keypair, "ElGamal pubkey"); } Ok(elgamal_keypair) } -fn confirm_elgamal_keypair_pubkey(keypair: &ElGamalKeypair) { - let elgamal_pubkey = keypair.public; - print!("Recovered ElGamal pubkey `{elgamal_pubkey:?}`. Continue? (y/n): "); +fn confirm_encodable_keypair_pubkey(keypair: &K, pubkey_label: &str) { + let pubkey = keypair.encodable_pubkey().to_string(); + println!("Recovered {pubkey_label} `{pubkey:?}`. Continue? (y/n): "); let _ignored = stdout().flush(); let mut input = String::new(); stdin().read_line(&mut input).expect("Unexpected input"); @@ -1175,7 +1163,7 @@ pub fn keypair_from_seed_phrase( let keypair: Keypair = encodable_key_from_seed_phrase(keypair_name, skip_validation, derivation_path, legacy)?; if confirm_pubkey { - confirm_keypair_pubkey(&keypair); + confirm_encodable_keypair_pubkey(&keypair, "pubkey"); } Ok(keypair) } @@ -1198,7 +1186,7 @@ pub fn elgamal_keypair_from_seed_phrase( legacy, )?; if confirm_pubkey { - confirm_elgamal_keypair_pubkey(&elgamal_keypair); + confirm_encodable_keypair_pubkey(&elgamal_keypair, "ElGamal pubkey"); } Ok(elgamal_keypair) } diff --git a/sdk/src/signer/keypair.rs b/sdk/src/signer/keypair.rs index e000bd86c..c6a911fdd 100644 --- a/sdk/src/signer/keypair.rs +++ b/sdk/src/signer/keypair.rs @@ -5,7 +5,7 @@ use { derivation_path::DerivationPath, pubkey::Pubkey, signature::Signature, - signer::{EncodableKey, Signer, SignerError}, + signer::{EncodableKey, EncodableKeypair, Signer, SignerError}, }, ed25519_dalek::Signer as DalekSigner, ed25519_dalek_bip32::Error as Bip32Error, @@ -140,6 +140,16 @@ impl EncodableKey for Keypair { } } +impl EncodableKeypair for Keypair { + type Pubkey = Pubkey; + + /// Returns the associated pubkey. Use this function specifically for settings that involve + /// reading or writing pubkeys. For other settings, use `Signer::pubkey()` instead. + fn encodable_pubkey(&self) -> Self::Pubkey { + self.pubkey() + } +} + /// Reads a JSON-encoded `Keypair` from a `Reader` implementor pub fn read_keypair(reader: &mut R) -> Result> { let bytes: Vec = serde_json::from_reader(reader)?; diff --git a/sdk/src/signer/mod.rs b/sdk/src/signer/mod.rs index 84db07c0f..94add04f4 100644 --- a/sdk/src/signer/mod.rs +++ b/sdk/src/signer/mod.rs @@ -155,6 +155,15 @@ pub trait EncodableKey: Sized { ) -> Result>; } +/// The `EncodableKeypair` trait extends `EncodableKey` for asymmetric keypairs, i.e. have +/// associated public keys. +pub trait EncodableKeypair: EncodableKey { + type Pubkey: ToString; + + /// Returns an encodable representation of the associated public key. + fn encodable_pubkey(&self) -> Self::Pubkey; +} + #[cfg(test)] mod tests { use {super::*, crate::signer::keypair::Keypair}; diff --git a/zk-token-sdk/src/encryption/elgamal.rs b/zk-token-sdk/src/encryption/elgamal.rs index 8c9d10bc2..d77051301 100644 --- a/zk-token-sdk/src/encryption/elgamal.rs +++ b/zk-token-sdk/src/encryption/elgamal.rs @@ -33,8 +33,8 @@ use { pubkey::Pubkey, signature::Signature, signer::{ - keypair::generate_seed_from_seed_phrase_and_passphrase, EncodableKey, Signer, - SignerError, + keypair::generate_seed_from_seed_phrase_and_passphrase, EncodableKey, EncodableKeypair, + Signer, SignerError, }, }, std::convert::TryInto, @@ -273,6 +273,14 @@ impl EncodableKey for ElGamalKeypair { } } +impl EncodableKeypair for ElGamalKeypair { + type Pubkey = ElGamalPubkey; + + fn encodable_pubkey(&self) -> Self::Pubkey { + self.public + } +} + /// Public key for the ElGamal encryption scheme. #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, Zeroize)] pub struct ElGamalPubkey(RistrettoPoint);