Add Ledger error codes (#10056)

automerge
This commit is contained in:
Tyera Eulberg
2020-05-14 22:52:11 -06:00
committed by GitHub
parent adcd2f14a5
commit 63813fe69f
7 changed files with 169 additions and 50 deletions

View File

@@ -1,9 +1,13 @@
use crate::remote_wallet::{
DerivationPath, RemoteWallet, RemoteWalletError, RemoteWalletInfo, RemoteWalletManager,
use crate::{
ledger_error::LedgerError,
remote_wallet::{
DerivationPath, RemoteWallet, RemoteWalletError, RemoteWalletInfo, RemoteWalletManager,
},
};
use console::Emoji;
use dialoguer::{theme::ColorfulTheme, Select};
use log::*;
use num_traits::FromPrimitive;
use semver::Version as FirmwareVersion;
use solana_sdk::{pubkey::Pubkey, signature::Signature};
use std::{cmp::min, fmt, sync::Arc};
@@ -30,6 +34,8 @@ const P2_EXTEND: u8 = 0x01;
const P2_MORE: u8 = 0x02;
const MAX_CHUNK_SIZE: usize = 255;
const APDU_SUCCESS_CODE: usize = 0x9000;
const SOL_DERIVATION_PATH_BE: [u8; 8] = [0x80, 0, 0, 44, 0x80, 0, 0x01, 0xF5]; // 44'/501', Solana
/// Ledger vendor ID
@@ -231,33 +237,7 @@ impl LedgerWallet {
let status =
(message[message.len() - 2] as usize) << 8 | (message[message.len() - 1] as usize);
trace!("Read status {:x}", status);
#[allow(clippy::match_overlapping_arm)]
match status {
// These need to be aligned with solana Ledger app error codes, and clippy allowance removed
0x6700 => Err(RemoteWalletError::Protocol(
"Solana app not open on Ledger device",
)),
0x6802 => Err(RemoteWalletError::Protocol("Invalid parameter")),
0x6803 => Err(RemoteWalletError::Protocol(
"Overflow: message longer than MAX_MESSAGE_LENGTH",
)),
0x6982 => Err(RemoteWalletError::Protocol(
"Security status not satisfied (Canceled by user)",
)),
0x6985 => Err(RemoteWalletError::UserCancel),
0x6a80 => Err(RemoteWalletError::Protocol("Invalid data")),
0x6a82 => Err(RemoteWalletError::Protocol("File not found")),
0x6b00 => Err(RemoteWalletError::Protocol("Incorrect parameters")),
0x6d00 => Err(RemoteWalletError::Protocol(
"Not implemented. Make sure the Ledger Solana Wallet app is running.",
)),
0x6faa => Err(RemoteWalletError::Protocol(
"Your Ledger device needs to be unplugged",
)),
0x6f00..=0x6fff => Err(RemoteWalletError::Protocol("Internal error")),
0x9000 => Ok(()),
_ => Err(RemoteWalletError::Protocol("Unknown error")),
}?;
Self::parse_status(status)?;
let new_len = message.len() - 2;
message.truncate(new_len);
Ok(message)
@@ -311,6 +291,16 @@ impl LedgerWallet {
fn outdated_app(&self) -> bool {
self.version < DEPRECATE_VERSION_BEFORE
}
fn parse_status(status: usize) -> Result<(), RemoteWalletError> {
if status == APDU_SUCCESS_CODE {
Ok(())
} else if let Some(err) = LedgerError::from_usize(status) {
Err(err.into())
} else {
Err(RemoteWalletError::Protocol("Unknown error"))
}
}
}
impl RemoteWallet for LedgerWallet {
@@ -582,4 +572,16 @@ mod tests {
assert!(!is_last_part(p2));
assert!(is_last_part(p2 & !P2_MORE));
}
#[test]
fn test_parse_status() {
assert_eq!(LedgerWallet::parse_status(APDU_SUCCESS_CODE).unwrap(), ());
if let RemoteWalletError::LedgerError(err) = LedgerWallet::parse_status(0x6985).unwrap_err()
{
assert_eq!(err, LedgerError::UserCancel);
}
if let RemoteWalletError::Protocol(err) = LedgerWallet::parse_status(0x6fff).unwrap_err() {
assert_eq!(err, "Unknown error");
}
}
}