[clap-v3-utils] Add `EncodableKeypair` trait and make `confirm_keypair_pubkey` generic (#31642)

* add `EncodableKeypair` trait

* implement `EncodableKeypair` for `Keypair`

* implement `EncodableKeypair` for `ElGamalKeypair

* make confirm pubkey functions generic

* fix a typo

* Update sdk/src/signer/keypair.rs

Co-authored-by: Trent Nelson <trent.a.b.nelson@gmail.com>

* Update clap-v3-utils/src/keypair.rs

Co-authored-by: Tyera <teulberg@gmail.com>

* fix a typo

---------

Co-authored-by: Trent Nelson <trent.a.b.nelson@gmail.com>
Co-authored-by: Tyera <teulberg@gmail.com>
This commit is contained in:
samkim-crypto 2023-05-17 05:37:59 +09:00 committed by GitHub
parent ad67fd5be5
commit e14384d8ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 23 deletions

View File

@ -30,7 +30,7 @@ use {
pubkey::Pubkey, pubkey::Pubkey,
signature::{ signature::{
generate_seed_from_seed_phrase_and_passphrase, read_keypair, read_keypair_file, 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}, solana_zk_token_sdk::encryption::{auth_encryption::AeKey, elgamal::ElGamalKeypair},
@ -1004,23 +1004,11 @@ pub fn keypair_from_path(
) -> Result<Keypair, Box<dyn error::Error>> { ) -> Result<Keypair, Box<dyn error::Error>> {
let keypair = encodable_key_from_path(matches, path, keypair_name)?; let keypair = encodable_key_from_path(matches, path, keypair_name)?;
if confirm_pubkey { if confirm_pubkey {
confirm_keypair_pubkey(&keypair); confirm_encodable_keypair_pubkey(&keypair, "pubkey");
} }
Ok(keypair) 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. /// Loads an [ElGamalKeypair] from one of several possible sources.
/// ///
/// If `confirm_pubkey` is `true` then after deriving the keypair, the user will /// If `confirm_pubkey` is `true` then after deriving the keypair, the user will
@ -1063,14 +1051,14 @@ pub fn elgamal_keypair_from_path(
) -> Result<ElGamalKeypair, Box<dyn error::Error>> { ) -> Result<ElGamalKeypair, Box<dyn error::Error>> {
let elgamal_keypair = encodable_key_from_path(matches, path, elgamal_keypair_name)?; let elgamal_keypair = encodable_key_from_path(matches, path, elgamal_keypair_name)?;
if confirm_pubkey { if confirm_pubkey {
confirm_elgamal_keypair_pubkey(&elgamal_keypair); confirm_encodable_keypair_pubkey(&elgamal_keypair, "ElGamal pubkey");
} }
Ok(elgamal_keypair) Ok(elgamal_keypair)
} }
fn confirm_elgamal_keypair_pubkey(keypair: &ElGamalKeypair) { fn confirm_encodable_keypair_pubkey<K: EncodableKeypair>(keypair: &K, pubkey_label: &str) {
let elgamal_pubkey = keypair.public; let pubkey = keypair.encodable_pubkey().to_string();
print!("Recovered ElGamal pubkey `{elgamal_pubkey:?}`. Continue? (y/n): "); println!("Recovered {pubkey_label} `{pubkey:?}`. Continue? (y/n): ");
let _ignored = stdout().flush(); let _ignored = stdout().flush();
let mut input = String::new(); let mut input = String::new();
stdin().read_line(&mut input).expect("Unexpected input"); stdin().read_line(&mut input).expect("Unexpected input");
@ -1175,7 +1163,7 @@ pub fn keypair_from_seed_phrase(
let keypair: Keypair = let keypair: Keypair =
encodable_key_from_seed_phrase(keypair_name, skip_validation, derivation_path, legacy)?; encodable_key_from_seed_phrase(keypair_name, skip_validation, derivation_path, legacy)?;
if confirm_pubkey { if confirm_pubkey {
confirm_keypair_pubkey(&keypair); confirm_encodable_keypair_pubkey(&keypair, "pubkey");
} }
Ok(keypair) Ok(keypair)
} }
@ -1198,7 +1186,7 @@ pub fn elgamal_keypair_from_seed_phrase(
legacy, legacy,
)?; )?;
if confirm_pubkey { if confirm_pubkey {
confirm_elgamal_keypair_pubkey(&elgamal_keypair); confirm_encodable_keypair_pubkey(&elgamal_keypair, "ElGamal pubkey");
} }
Ok(elgamal_keypair) Ok(elgamal_keypair)
} }

View File

@ -5,7 +5,7 @@ use {
derivation_path::DerivationPath, derivation_path::DerivationPath,
pubkey::Pubkey, pubkey::Pubkey,
signature::Signature, signature::Signature,
signer::{EncodableKey, Signer, SignerError}, signer::{EncodableKey, EncodableKeypair, Signer, SignerError},
}, },
ed25519_dalek::Signer as DalekSigner, ed25519_dalek::Signer as DalekSigner,
ed25519_dalek_bip32::Error as Bip32Error, 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 /// Reads a JSON-encoded `Keypair` from a `Reader` implementor
pub fn read_keypair<R: Read>(reader: &mut R) -> Result<Keypair, Box<dyn error::Error>> { pub fn read_keypair<R: Read>(reader: &mut R) -> Result<Keypair, Box<dyn error::Error>> {
let bytes: Vec<u8> = serde_json::from_reader(reader)?; let bytes: Vec<u8> = serde_json::from_reader(reader)?;

View File

@ -155,6 +155,15 @@ pub trait EncodableKey: Sized {
) -> Result<Self, Box<dyn error::Error>>; ) -> Result<Self, Box<dyn error::Error>>;
} }
/// 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)] #[cfg(test)]
mod tests { mod tests {
use {super::*, crate::signer::keypair::Keypair}; use {super::*, crate::signer::keypair::Keypair};

View File

@ -33,8 +33,8 @@ use {
pubkey::Pubkey, pubkey::Pubkey,
signature::Signature, signature::Signature,
signer::{ signer::{
keypair::generate_seed_from_seed_phrase_and_passphrase, EncodableKey, Signer, keypair::generate_seed_from_seed_phrase_and_passphrase, EncodableKey, EncodableKeypair,
SignerError, Signer, SignerError,
}, },
}, },
std::convert::TryInto, 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. /// Public key for the ElGamal encryption scheme.
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, Zeroize)] #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, Zeroize)]
pub struct ElGamalPubkey(RistrettoPoint); pub struct ElGamalPubkey(RistrettoPoint);