Add hidapi feature in remote-wallet
This commit is contained in:
committed by
Trent Nelson
parent
e291342c4a
commit
b635073829
@ -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"
|
||||||
|
12
programs/bpf/Cargo.lock
generated
12
programs/bpf/Cargo.lock
generated
@ -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",
|
||||||
|
@ -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"]
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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()?;
|
||||||
|
Reference in New Issue
Block a user