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"
rpassword = "5.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" }
thiserror = "1.0.30"
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"
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]]
name = "hmac"
version = "0.8.1"
@ -3469,7 +3458,6 @@ version = "1.10.0"
dependencies = [
"console",
"dialoguer",
"hidapi",
"log",
"num-derive",
"num-traits",

View File

@ -12,7 +12,7 @@ documentation = "https://docs.rs/solana-remote-wallet"
[dependencies]
console = "0.15.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"
num-derive = { version = "0.3" }
num-traits = { version = "0.2" }
@ -24,7 +24,7 @@ thiserror = "1.0"
uriparse = "0.6.3"
[features]
default = ["linux-static-hidraw"]
default = ["linux-static-hidraw", "hidapi"]
linux-static-libusb = ["hidapi/linux-static-libusb"]
linux-static-hidraw = ["hidapi/linux-static-hidraw"]
linux-shared-libusb = ["hidapi/linux-shared-libusb"]

View File

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

View File

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

View File

@ -1,11 +1,13 @@
#[cfg(feature = "hidapi")]
use {crate::ledger::is_valid_ledger, parking_lot::Mutex};
use {
crate::{
ledger::{is_valid_ledger, LedgerWallet},
ledger::LedgerWallet,
ledger_error::LedgerError,
locator::{Locator, LocatorError, Manufacturer},
},
log::*,
parking_lot::{Mutex, RwLock},
parking_lot::RwLock,
solana_sdk::{
derivation_path::{DerivationPath, DerivationPathError},
pubkey::Pubkey,
@ -61,6 +63,7 @@ pub enum RemoteWalletError {
LocatorError(#[from] LocatorError),
}
#[cfg(feature = "hidapi")]
impl From<hidapi::HidError> for RemoteWalletError {
fn from(err: hidapi::HidError) -> RemoteWalletError {
RemoteWalletError::Hid(err.to_string())
@ -87,12 +90,14 @@ impl From<RemoteWalletError> for SignerError {
/// Collection of connected RemoteWallets
pub struct RemoteWalletManager {
#[cfg(feature = "hidapi")]
usb: Arc<Mutex<hidapi::HidApi>>,
devices: RwLock<Vec<Device>>,
}
impl RemoteWalletManager {
/// Create a new instance.
#[cfg(feature = "hidapi")]
pub fn new(usb: Arc<Mutex<hidapi::HidApi>>) -> Arc<Self> {
Arc::new(Self {
usb,
@ -102,6 +107,7 @@ impl RemoteWalletManager {
/// Repopulate device list
/// Note: this method iterates over and updates all devices
#[cfg(feature = "hidapi")]
pub fn update_devices(&self) -> Result<usize, RemoteWalletError> {
let mut usb = self.usb.lock();
usb.refresh_devices()?;
@ -149,6 +155,13 @@ impl RemoteWalletManager {
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
pub fn list_devices(&self) -> Vec<RemoteWalletInfo> {
self.devices.read().iter().map(|d| d.info.clone()).collect()
@ -195,30 +208,34 @@ impl RemoteWalletManager {
}
/// `RemoteWallet` trait
pub trait RemoteWallet {
#[allow(unused_variables)]
pub trait RemoteWallet<T> {
fn name(&self) -> &str {
"remote wallet"
}
/// Parse device info and get device base pubkey
fn read_device(
&mut self,
dev_info: &hidapi::DeviceInfo,
) -> Result<RemoteWalletInfo, RemoteWalletError>;
fn read_device(&mut self, dev_info: &T) -> Result<RemoteWalletInfo, RemoteWalletError> {
unreachable!();
}
/// Get solana pubkey from a RemoteWallet
fn get_pubkey(
&self,
derivation_path: &DerivationPath,
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>'.
fn sign_message(
&self,
derivation_path: &DerivationPath,
data: &[u8],
) -> Result<Signature, RemoteWalletError>;
) -> Result<Signature, RemoteWalletError> {
unreachable!();
}
}
/// `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
#[cfg(feature = "hidapi")]
pub fn initialize_wallet_manager() -> Result<Arc<RemoteWalletManager>, RemoteWalletError> {
let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new()?));
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> {
let wallet_manager = initialize_wallet_manager()?;