Enable remote-wallet signing in solana-keygen (#8267)

* Add fallible methods to KeypairUtil

* Add RemoteKeypair struct and impl KeypairUtil

* Implement RemoteKeypair in keygen; also add parse_keypair_path for cleanup
This commit is contained in:
Tyera Eulberg
2020-02-13 14:08:35 -07:00
committed by GitHub
parent ab475e4849
commit 2374cf09e2
8 changed files with 150 additions and 85 deletions

View File

@@ -1,5 +1,9 @@
use crate::remote_wallet::{
initialize_wallet_manager, DerivationPath, RemoteWallet, RemoteWalletError, RemoteWalletInfo,
use crate::{
remote_keypair::RemoteKeypair,
remote_wallet::{
initialize_wallet_manager, DerivationPath, RemoteWallet, RemoteWalletError,
RemoteWalletInfo, RemoteWalletType,
},
};
use dialoguer::{theme::ColorfulTheme, Select};
use log::*;
@@ -365,3 +369,13 @@ pub fn get_ledger_from_info(
};
wallet_manager.get_ledger(&wallet_base_pubkey)
}
pub fn generate_remote_keypair(
ledger: Arc<LedgerWallet>,
derivation_path: DerivationPath,
) -> RemoteKeypair {
RemoteKeypair {
wallet_type: RemoteWalletType::Ledger(ledger),
derivation_path,
}
}

View File

@@ -1,2 +1,3 @@
pub mod ledger;
pub mod remote_keypair;
pub mod remote_wallet;

View File

@@ -0,0 +1,38 @@
use crate::remote_wallet::{DerivationPath, RemoteWallet, RemoteWalletType};
use solana_sdk::{
pubkey::Pubkey,
signature::{KeypairUtil, Signature},
};
use std::error;
pub struct RemoteKeypair {
pub wallet_type: RemoteWalletType,
pub derivation_path: DerivationPath,
}
impl RemoteKeypair {
pub fn new(wallet_type: RemoteWalletType, derivation_path: DerivationPath) -> Self {
Self {
wallet_type,
derivation_path,
}
}
}
impl KeypairUtil for RemoteKeypair {
fn try_pubkey(&self) -> Result<Pubkey, Box<dyn error::Error>> {
match &self.wallet_type {
RemoteWalletType::Ledger(wallet) => wallet
.get_pubkey(&self.derivation_path)
.map_err(|e| e.into()),
}
}
fn try_sign_message(&self, message: &[u8]) -> Result<Signature, Box<dyn error::Error>> {
match &self.wallet_type {
RemoteWalletType::Ledger(wallet) => wallet
.sign_message(&self.derivation_path, message)
.map_err(|e| e.into()),
}
}
}

View File

@@ -192,7 +192,6 @@ pub struct RemoteWalletInfo {
impl RemoteWalletInfo {
pub fn parse_path(mut path: String) -> Result<(Self, DerivationPath), RemoteWalletError> {
let mut path = path.split_off(6);
if path.ends_with('/') {
path.pop();
}
@@ -288,7 +287,22 @@ mod tests {
fn test_parse_path() {
let pubkey = Pubkey::new_rand();
let (wallet_info, derivation_path) =
RemoteWalletInfo::parse_path(format!("usb://ledger/nano-s/{:?}/44/501/1/2", pubkey))
RemoteWalletInfo::parse_path(format!("ledger/nano-s/{:?}/44/501/1/2", pubkey)).unwrap();
assert!(wallet_info.matches(&RemoteWalletInfo {
model: "nano-s".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
pubkey,
}));
assert_eq!(
derivation_path,
DerivationPath {
account: 1,
change: Some(2),
}
);
let (wallet_info, derivation_path) =
RemoteWalletInfo::parse_path(format!("ledger/nano-s/{:?}/44'/501'/1'/2'", pubkey))
.unwrap();
assert!(wallet_info.matches(&RemoteWalletInfo {
model: "nano-s".to_string(),
@@ -303,35 +317,13 @@ mod tests {
change: Some(2),
}
);
let (wallet_info, derivation_path) = RemoteWalletInfo::parse_path(format!(
"usb://ledger/nano-s/{:?}/44'/501'/1'/2'",
pubkey
))
.unwrap();
assert!(wallet_info.matches(&RemoteWalletInfo {
model: "nano-s".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
pubkey,
}));
assert_eq!(
derivation_path,
DerivationPath {
account: 1,
change: Some(2),
}
);
assert!(RemoteWalletInfo::parse_path(format!(
"usb://ledger/nano-s/{:?}/43/501/1/2",
pubkey
))
.is_err());
assert!(RemoteWalletInfo::parse_path(format!(
"usb://ledger/nano-s/{:?}/44/500/1/2",
pubkey
))
.is_err());
assert!(
RemoteWalletInfo::parse_path(format!("ledger/nano-s/{:?}/43/501/1/2", pubkey)).is_err()
);
assert!(
RemoteWalletInfo::parse_path(format!("ledger/nano-s/{:?}/44/500/1/2", pubkey)).is_err()
);
}
#[test]