diff --git a/Cargo.lock b/Cargo.lock index 59cace36e..c66829f6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4735,7 +4735,6 @@ dependencies = [ "soroban-spec-rust", "soroban-spec-tools", "soroban-spec-typescript", - "stellar-ledger", "stellar-rpc-client", "stellar-strkey", "stellar-xdr", diff --git a/cmd/crates/stellar-ledger/src/hd_path.rs b/cmd/crates/stellar-ledger/src/hd_path.rs index 4a207d644..07ed133f1 100644 --- a/cmd/crates/stellar-ledger/src/hd_path.rs +++ b/cmd/crates/stellar-ledger/src/hd_path.rs @@ -1,8 +1,9 @@ +use crate::Error; + #[derive(Clone, Copy)] pub struct HdPath(pub u32); impl HdPath { - #[must_use] pub fn depth(&self) -> u8 { let path: slip10::BIP32Path = self.into(); path.depth() @@ -22,8 +23,7 @@ impl From<&u32> for HdPath { } impl HdPath { - #[must_use] - pub fn to_vec(&self) -> Vec { + pub fn to_vec(&self) -> Result, Error> { hd_path_to_bytes(&self.into()) } } @@ -35,11 +35,16 @@ impl From<&HdPath> for slip10::BIP32Path { } } -fn hd_path_to_bytes(hd_path: &slip10::BIP32Path) -> Vec { +fn hd_path_to_bytes(hd_path: &slip10::BIP32Path) -> Result, Error> { let hd_path_indices = 0..hd_path.depth(); - // Unsafe unwrap is safe because the depth is the length of interneal vector - hd_path_indices + let result = hd_path_indices .into_iter() - .flat_map(|index| unsafe { hd_path.index(index).unwrap_unchecked().to_be_bytes() }) - .collect() + .map(|index| { + Ok(hd_path + .index(index) + .ok_or_else(|| Error::Bip32PathError(format!("{hd_path}")))? + .to_be_bytes()) + }) + .collect::, Error>>()?; + Ok(result.into_iter().flatten().collect()) } diff --git a/cmd/crates/stellar-ledger/src/lib.rs b/cmd/crates/stellar-ledger/src/lib.rs index 69789b735..c74365af2 100644 --- a/cmd/crates/stellar-ledger/src/lib.rs +++ b/cmd/crates/stellar-ledger/src/lib.rs @@ -1,9 +1,8 @@ use hd_path::HdPath; -use ledger_transport::APDUCommand; -pub use ledger_transport_hid::TransportNativeHID; +use ledger_transport::{APDUCommand, Exchange}; use ledger_transport_hid::{ hidapi::{HidApi, HidError}, - LedgerHIDError, + LedgerHIDError, TransportNativeHID, }; use soroban_env_host::xdr::{Hash, Transaction}; @@ -16,8 +15,6 @@ use stellar_xdr::curr::{ pub use crate::signer::Blob; pub mod hd_path; -pub use ledger_transport::Exchange; - mod signer; // this is from https://github.com/LedgerHQ/ledger-live/blob/36cfbf3fa3300fd99bcee2ab72e1fd8f280e6280/libs/ledgerjs/packages/hw-app-str/src/Str.ts#L181 @@ -83,11 +80,6 @@ pub struct LedgerSigner { unsafe impl Send for LedgerSigner where T: Exchange {} unsafe impl Sync for LedgerSigner where T: Exchange {} -/// Returns a new `LedgerSigner` with a native HID transport, e.i. the transport is connected to the Ledger device -/// -/// # Errors -/// -/// Returns an error if there is an issue with connecting with the device pub fn native() -> Result, Error> { Ok(LedgerSigner { transport: get_transport()?, @@ -101,7 +93,11 @@ where pub fn new(transport: T) -> Self { Self { transport } } - + pub fn native() -> Result, Error> { + Ok(LedgerSigner { + transport: get_transport()?, + }) + } /// Get the device app's configuration /// # Errors /// Returns an error if there is an issue with connecting with the device or getting the config from the device @@ -145,7 +141,7 @@ where }; let mut signature_payload_as_bytes = signature_payload.to_xdr(Limits::none())?; - let mut hd_path_to_bytes = hd_path.into().to_vec(); + let mut hd_path_to_bytes = hd_path.into().to_vec()?; let capacity = 1 + hd_path_to_bytes.len() + signature_payload_as_bytes.len(); let mut data: Vec = Vec::with_capacity(capacity); @@ -186,9 +182,7 @@ where } /// The `display_and_confirm` bool determines if the Ledger will display the public key on its screen and requires user approval to share - /// # Errors - /// Returns an error if there is an issue with connecting with the device or getting the public key from the device - pub async fn get_public_key_with_display_flag( + async fn get_public_key_with_display_flag( &self, hd_path: impl Into, display_and_confirm: bool, @@ -197,7 +191,7 @@ where // the first element of the data should be the number of elements in the path let hd_path = hd_path.into(); let hd_path_elements_count = hd_path.depth(); - let mut hd_path_to_bytes = hd_path.to_vec(); + let mut hd_path_to_bytes = hd_path.to_vec()?; hd_path_to_bytes.insert(0, hd_path_elements_count); let p2 = if display_and_confirm { @@ -247,30 +241,6 @@ where )), } } - - /// Sign a blob of data with the account on the Ledger device - /// # Errors - /// Returns an error if there is an issue with connecting with the device or signing the given tx on the device - pub async fn sign_data(&self, index: &HdPath, blob: &[u8]) -> Result, Error> { - let mut hd_path_to_bytes = index.to_vec(); - - let capacity = 1 + hd_path_to_bytes.len() + blob.len(); - let mut data: Vec = Vec::with_capacity(capacity); - - data.insert(0, HD_PATH_ELEMENTS_COUNT); - data.append(&mut hd_path_to_bytes); - data.extend_from_slice(blob); - - let command = APDUCommand { - cla: CLA, - ins: SIGN_TX_HASH, - p1: P1_SIGN_TX_HASH, - p2: P2_SIGN_TX_HASH, - data, - }; - - self.send_command_to_ledger(command).await - } } #[async_trait::async_trait] @@ -295,7 +265,24 @@ where /// # Errors /// Returns an error if there is an issue with connecting with the device or signing the given tx on the device. Or, if the device has not enabled hash signing async fn sign_blob(&self, index: &Self::Key, blob: &[u8]) -> Result, Error> { - self.sign_data(index, blob).await + let mut hd_path_to_bytes = index.to_vec()?; + + let capacity = 1 + hd_path_to_bytes.len() + blob.len(); + let mut data: Vec = Vec::with_capacity(capacity); + + data.insert(0, HD_PATH_ELEMENTS_COUNT); + data.append(&mut hd_path_to_bytes); + data.extend_from_slice(blob); + + let command = APDUCommand { + cla: CLA, + ins: SIGN_TX_HASH, + p1: P1_SIGN_TX_HASH, + p2: P2_SIGN_TX_HASH, + data, + }; + + self.send_command_to_ledger(command).await } } diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index d8eb044de..aa293d3fd 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -50,7 +50,6 @@ soroban-ledger-snapshot = { workspace = true } stellar-strkey = { workspace = true } soroban-sdk = { workspace = true } soroban-rpc = { workspace = true } -stellar-ledger = { workspace = true } clap = { workspace = true, features = [ "derive", diff --git a/cmd/soroban-cli/src/commands/config/secret.rs b/cmd/soroban-cli/src/commands/config/secret.rs index 36a49608f..dfc4784ce 100644 --- a/cmd/soroban-cli/src/commands/config/secret.rs +++ b/cmd/soroban-cli/src/commands/config/secret.rs @@ -4,7 +4,7 @@ use std::{io::Write, str::FromStr}; use stellar_strkey::ed25519::{PrivateKey, PublicKey}; use crate::{ - signer::{self, native, Ledger, LocalKey, Stellar}, + signer::{self, LocalKey, Stellar}, utils, }; @@ -79,7 +79,6 @@ impl Args { pub enum SignerKind { SecretKey { secret_key: String }, SeedPhrase { seed_phrase: String }, - Ledger, } impl FromStr for SignerKind { @@ -94,8 +93,6 @@ impl FromStr for SignerKind { Ok(SignerKind::SeedPhrase { seed_phrase: s.to_string(), }) - } else if s == "ledger" { - Ok(SignerKind::Ledger) } else { Err(Error::InvalidAddress(s.to_string())) } @@ -120,7 +117,6 @@ impl SignerKind { .private() .0, )?, - SignerKind::Ledger => panic!("Ledger does not reveal secret key"), }) } @@ -134,13 +130,6 @@ impl SignerKind { SignerKind::SecretKey { .. } | SignerKind::SeedPhrase { .. } => Ok( StellarSigner::Local(LocalKey::new(self.key_pair(index)?, prompt)), ), - SignerKind::Ledger => { - let hd_path: u32 = index - .unwrap_or_default() - .try_into() - .expect("uszie bigger than u32"); - Ok(StellarSigner::Ledger(native(hd_path)?)) - } } } @@ -166,21 +155,18 @@ impl SignerKind { pub enum StellarSigner { Local(LocalKey), - Ledger(Ledger), } impl Stellar for StellarSigner { async fn get_public_key(&self) -> Result { match self { StellarSigner::Local(signer) => signer.get_public_key().await, - StellarSigner::Ledger(signer) => signer.get_public_key().await, } } async fn sign_blob(&self, blob: &[u8]) -> Result, signer::Error> { match self { StellarSigner::Local(signer) => signer.sign_blob(blob).await, - StellarSigner::Ledger(signer) => signer.sign_blob(blob).await, } } } diff --git a/cmd/soroban-cli/src/signer.rs b/cmd/soroban-cli/src/signer.rs index af865b110..acc92ca77 100644 --- a/cmd/soroban-cli/src/signer.rs +++ b/cmd/soroban-cli/src/signer.rs @@ -10,7 +10,6 @@ use crate::xdr::{ TransactionSignaturePayload, TransactionSignaturePayloadTaggedTransaction, TransactionV1Envelope, Uint256, WriteXdr, }; -use stellar_ledger::{Exchange, LedgerSigner}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -21,8 +20,6 @@ pub enum Error { #[error("Missing signing key for account {address}")] MissingSignerForAddress { address: String }, #[error(transparent)] - Ledger(#[from] stellar_ledger::Error), - #[error(transparent)] Xdr(#[from] xdr::Error), #[error("User cancelled signing, perhaps need to remove --check")] UserCancelledSigning, @@ -248,32 +245,6 @@ impl Stellar for LocalKey { } } -pub struct Ledger { - index: u32, - signer: LedgerSigner, -} - -pub fn native(index: u32) -> Result, Error> { - let signer = stellar_ledger::native()?; - Ok(Ledger { index, signer }) -} - -impl Stellar for Ledger -where - T: Exchange, -{ - async fn get_public_key(&self) -> Result { - Ok(self - .signer - .get_public_key_with_display_flag(self.index, false) - .await?) - } - - async fn sign_blob(&self, blob: &[u8]) -> Result, Error> { - Ok(self.signer.sign_data(&self.index.into(), blob).await?) - } -} - pub fn read_key() -> char { let tty = get_tty().unwrap(); if let Some(key) = tty.keys().next() {