Add hidapi feature in remote-wallet

This commit is contained in:
Eric Warehime
2021-12-06 14:32:59 -08:00
committed by Trent Nelson
parent e291342c4a
commit b635073829
6 changed files with 54 additions and 32 deletions

View File

@ -13,7 +13,7 @@ edition = "2021"
clap = "2.33.0" clap = "2.33.0"
rpassword = "5.0" rpassword = "5.0"
solana-perf = { path = "../perf", version = "=1.10.0" } solana-perf = { path = "../perf", version = "=1.10.0" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.10.0" } solana-remote-wallet = { path = "../remote-wallet", version = "=1.10.0", default-features = false}
solana-sdk = { path = "../sdk", version = "=1.10.0" } solana-sdk = { path = "../sdk", version = "=1.10.0" }
thiserror = "1.0.30" thiserror = "1.0.30"
tiny-bip39 = "0.8.2" tiny-bip39 = "0.8.2"

View File

@ -1242,17 +1242,6 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hidapi"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c4cc7279df8353788ac551186920e44959d5948aec404be02b28544a598bce"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]] [[package]]
name = "hmac" name = "hmac"
version = "0.8.1" version = "0.8.1"
@ -3469,7 +3458,6 @@ version = "1.10.0"
dependencies = [ dependencies = [
"console", "console",
"dialoguer", "dialoguer",
"hidapi",
"log", "log",
"num-derive", "num-derive",
"num-traits", "num-traits",

View File

@ -12,7 +12,7 @@ documentation = "https://docs.rs/solana-remote-wallet"
[dependencies] [dependencies]
console = "0.15.0" console = "0.15.0"
dialoguer = "0.9.0" dialoguer = "0.9.0"
hidapi = { version = "1.3.2", default-features = false } hidapi = { version = "1.3.2", default-features = false, optional = true}
log = "0.4.14" log = "0.4.14"
num-derive = { version = "0.3" } num-derive = { version = "0.3" }
num-traits = { version = "0.2" } num-traits = { version = "0.2" }
@ -24,7 +24,7 @@ thiserror = "1.0"
uriparse = "0.6.3" uriparse = "0.6.3"
[features] [features]
default = ["linux-static-hidraw"] default = ["linux-static-hidraw", "hidapi"]
linux-static-libusb = ["hidapi/linux-static-libusb"] linux-static-libusb = ["hidapi/linux-static-libusb"]
linux-static-hidraw = ["hidapi/linux-static-hidraw"] linux-static-hidraw = ["hidapi/linux-static-hidraw"]
linux-shared-libusb = ["hidapi/linux-shared-libusb"] linux-shared-libusb = ["hidapi/linux-shared-libusb"]

View File

@ -1,16 +1,20 @@
use { use {
crate::{ crate::remote_wallet::{
ledger_error::LedgerError, RemoteWallet, RemoteWalletError, RemoteWalletInfo, RemoteWalletManager,
locator::Manufacturer,
remote_wallet::{RemoteWallet, RemoteWalletError, RemoteWalletInfo, RemoteWalletManager},
}, },
console::Emoji, console::Emoji,
dialoguer::{theme::ColorfulTheme, Select}, dialoguer::{theme::ColorfulTheme, Select},
semver::Version as FirmwareVersion,
solana_sdk::derivation_path::DerivationPath,
std::{fmt, sync::Arc},
};
#[cfg(feature = "hidapi")]
use {
crate::{ledger_error::LedgerError, locator::Manufacturer},
log::*, log::*,
num_traits::FromPrimitive, num_traits::FromPrimitive,
semver::Version as FirmwareVersion, solana_sdk::{pubkey::Pubkey, signature::Signature},
solana_sdk::{derivation_path::DerivationPath, pubkey::Pubkey, signature::Signature}, std::{cmp::min, convert::TryFrom},
std::{cmp::min, convert::TryFrom, fmt, sync::Arc},
}; };
static CHECK_MARK: Emoji = Emoji("", ""); static CHECK_MARK: Emoji = Emoji("", "");
@ -79,6 +83,7 @@ pub struct LedgerSettings {
/// Ledger Wallet device /// Ledger Wallet device
pub struct LedgerWallet { pub struct LedgerWallet {
#[cfg(feature = "hidapi")]
pub device: hidapi::HidDevice, pub device: hidapi::HidDevice,
pub pretty_path: String, pub pretty_path: String,
pub version: FirmwareVersion, pub version: FirmwareVersion,
@ -90,6 +95,7 @@ impl fmt::Debug for LedgerWallet {
} }
} }
#[cfg(feature = "hidapi")]
impl LedgerWallet { impl LedgerWallet {
pub fn new(device: hidapi::HidDevice) -> Self { pub fn new(device: hidapi::HidDevice) -> Self {
Self { Self {
@ -347,7 +353,10 @@ impl LedgerWallet {
} }
} }
impl RemoteWallet for LedgerWallet { #[cfg(not(feature = "hidapi"))]
impl RemoteWallet<Self> for LedgerWallet {}
#[cfg(feature = "hidapi")]
impl RemoteWallet<hidapi::DeviceInfo> for LedgerWallet {
fn name(&self) -> &str { fn name(&self) -> &str {
"Ledger hardware wallet" "Ledger hardware wallet"
} }

View File

@ -1,4 +1,5 @@
#![allow(clippy::integer_arithmetic)] #![allow(clippy::integer_arithmetic)]
#![allow(dead_code)]
pub mod ledger; pub mod ledger;
pub mod ledger_error; pub mod ledger_error;
pub mod locator; pub mod locator;

View File

@ -1,11 +1,13 @@
#[cfg(feature = "hidapi")]
use {crate::ledger::is_valid_ledger, parking_lot::Mutex};
use { use {
crate::{ crate::{
ledger::{is_valid_ledger, LedgerWallet}, ledger::LedgerWallet,
ledger_error::LedgerError, ledger_error::LedgerError,
locator::{Locator, LocatorError, Manufacturer}, locator::{Locator, LocatorError, Manufacturer},
}, },
log::*, log::*,
parking_lot::{Mutex, RwLock}, parking_lot::RwLock,
solana_sdk::{ solana_sdk::{
derivation_path::{DerivationPath, DerivationPathError}, derivation_path::{DerivationPath, DerivationPathError},
pubkey::Pubkey, pubkey::Pubkey,
@ -61,6 +63,7 @@ pub enum RemoteWalletError {
LocatorError(#[from] LocatorError), LocatorError(#[from] LocatorError),
} }
#[cfg(feature = "hidapi")]
impl From<hidapi::HidError> for RemoteWalletError { impl From<hidapi::HidError> for RemoteWalletError {
fn from(err: hidapi::HidError) -> RemoteWalletError { fn from(err: hidapi::HidError) -> RemoteWalletError {
RemoteWalletError::Hid(err.to_string()) RemoteWalletError::Hid(err.to_string())
@ -87,12 +90,14 @@ impl From<RemoteWalletError> for SignerError {
/// Collection of connected RemoteWallets /// Collection of connected RemoteWallets
pub struct RemoteWalletManager { pub struct RemoteWalletManager {
#[cfg(feature = "hidapi")]
usb: Arc<Mutex<hidapi::HidApi>>, usb: Arc<Mutex<hidapi::HidApi>>,
devices: RwLock<Vec<Device>>, devices: RwLock<Vec<Device>>,
} }
impl RemoteWalletManager { impl RemoteWalletManager {
/// Create a new instance. /// Create a new instance.
#[cfg(feature = "hidapi")]
pub fn new(usb: Arc<Mutex<hidapi::HidApi>>) -> Arc<Self> { pub fn new(usb: Arc<Mutex<hidapi::HidApi>>) -> Arc<Self> {
Arc::new(Self { Arc::new(Self {
usb, usb,
@ -102,6 +107,7 @@ impl RemoteWalletManager {
/// Repopulate device list /// Repopulate device list
/// Note: this method iterates over and updates all devices /// Note: this method iterates over and updates all devices
#[cfg(feature = "hidapi")]
pub fn update_devices(&self) -> Result<usize, RemoteWalletError> { pub fn update_devices(&self) -> Result<usize, RemoteWalletError> {
let mut usb = self.usb.lock(); let mut usb = self.usb.lock();
usb.refresh_devices()?; usb.refresh_devices()?;
@ -149,6 +155,13 @@ impl RemoteWalletManager {
Ok(num_curr_devices - num_prev_devices) Ok(num_curr_devices - num_prev_devices)
} }
#[cfg(not(feature = "hidapi"))]
pub fn update_devices(&self) -> Result<usize, RemoteWalletError> {
Err(RemoteWalletError::Hid(
"hidapi crate compilation disabled in solana-remote-wallet.".to_string(),
))
}
/// List connected and acknowledged wallets /// List connected and acknowledged wallets
pub fn list_devices(&self) -> Vec<RemoteWalletInfo> { pub fn list_devices(&self) -> Vec<RemoteWalletInfo> {
self.devices.read().iter().map(|d| d.info.clone()).collect() self.devices.read().iter().map(|d| d.info.clone()).collect()
@ -195,30 +208,34 @@ impl RemoteWalletManager {
} }
/// `RemoteWallet` trait /// `RemoteWallet` trait
pub trait RemoteWallet { #[allow(unused_variables)]
pub trait RemoteWallet<T> {
fn name(&self) -> &str { fn name(&self) -> &str {
"remote wallet" "remote wallet"
} }
/// Parse device info and get device base pubkey /// Parse device info and get device base pubkey
fn read_device( fn read_device(&mut self, dev_info: &T) -> Result<RemoteWalletInfo, RemoteWalletError> {
&mut self, unreachable!();
dev_info: &hidapi::DeviceInfo, }
) -> Result<RemoteWalletInfo, RemoteWalletError>;
/// Get solana pubkey from a RemoteWallet /// Get solana pubkey from a RemoteWallet
fn get_pubkey( fn get_pubkey(
&self, &self,
derivation_path: &DerivationPath, derivation_path: &DerivationPath,
confirm_key: bool, confirm_key: bool,
) -> Result<Pubkey, RemoteWalletError>; ) -> Result<Pubkey, RemoteWalletError> {
unreachable!();
}
/// Sign transaction data with wallet managing pubkey at derivation path m/44'/501'/<account>'/<change>'. /// Sign transaction data with wallet managing pubkey at derivation path m/44'/501'/<account>'/<change>'.
fn sign_message( fn sign_message(
&self, &self,
derivation_path: &DerivationPath, derivation_path: &DerivationPath,
data: &[u8], data: &[u8],
) -> Result<Signature, RemoteWalletError>; ) -> Result<Signature, RemoteWalletError> {
unreachable!();
}
} }
/// `RemoteWallet` device /// `RemoteWallet` device
@ -280,10 +297,17 @@ pub fn is_valid_hid_device(usage_page: u16, interface_number: i32) -> bool {
} }
/// Helper to initialize hidapi and RemoteWalletManager /// Helper to initialize hidapi and RemoteWalletManager
#[cfg(feature = "hidapi")]
pub fn initialize_wallet_manager() -> Result<Arc<RemoteWalletManager>, RemoteWalletError> { pub fn initialize_wallet_manager() -> Result<Arc<RemoteWalletManager>, RemoteWalletError> {
let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new()?)); let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new()?));
Ok(RemoteWalletManager::new(hidapi)) Ok(RemoteWalletManager::new(hidapi))
} }
#[cfg(not(feature = "hidapi"))]
pub fn initialize_wallet_manager() -> Result<Arc<RemoteWalletManager>, RemoteWalletError> {
Err(RemoteWalletError::Hid(
"hidapi crate compilation disabled in solana-remote-wallet.".to_string(),
))
}
pub fn maybe_wallet_manager() -> Result<Option<Arc<RemoteWalletManager>>, RemoteWalletError> { pub fn maybe_wallet_manager() -> Result<Option<Arc<RemoteWalletManager>>, RemoteWalletError> {
let wallet_manager = initialize_wallet_manager()?; let wallet_manager = initialize_wallet_manager()?;