Make solana root key accessible on Ledger (#8421)
* Use 44/501 key as ledger id * Add error codes
This commit is contained in:
parent
39282be486
commit
b7755123c1
|
@ -119,7 +119,7 @@ pub fn derivation_of(matches: &ArgMatches<'_>, name: &str) -> Option<DerivationP
|
||||||
matches.value_of(name).map(|derivation_str| {
|
matches.value_of(name).map(|derivation_str| {
|
||||||
let derivation_str = derivation_str.replace("'", "");
|
let derivation_str = derivation_str.replace("'", "");
|
||||||
let mut parts = derivation_str.split('/');
|
let mut parts = derivation_str.split('/');
|
||||||
let account = parts.next().unwrap().parse::<u16>().unwrap();
|
let account = parts.next().map(|account| account.parse::<u16>().unwrap());
|
||||||
let change = parts.next().map(|change| change.parse::<u16>().unwrap());
|
let change = parts.next().map(|change| change.parse::<u16>().unwrap());
|
||||||
DerivationPath { account, change }
|
DerivationPath { account, change }
|
||||||
})
|
})
|
||||||
|
@ -308,7 +308,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_of(&matches, "single"),
|
derivation_of(&matches, "single"),
|
||||||
Some(DerivationPath {
|
Some(DerivationPath {
|
||||||
account: 2,
|
account: Some(2),
|
||||||
change: Some(3)
|
change: Some(3)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -319,7 +319,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_of(&matches, "single"),
|
derivation_of(&matches, "single"),
|
||||||
Some(DerivationPath {
|
Some(DerivationPath {
|
||||||
account: 2,
|
account: Some(2),
|
||||||
change: None
|
change: None
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -330,7 +330,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_of(&matches, "single"),
|
derivation_of(&matches, "single"),
|
||||||
Some(DerivationPath {
|
Some(DerivationPath {
|
||||||
account: 2,
|
account: Some(2),
|
||||||
change: Some(3)
|
change: Some(3)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -193,6 +193,10 @@ impl LedgerWallet {
|
||||||
match status {
|
match status {
|
||||||
// These need to be aligned with solana Ledger app error codes, and clippy allowance removed
|
// These need to be aligned with solana Ledger app error codes, and clippy allowance removed
|
||||||
0x6700 => Err(RemoteWalletError::Protocol("Incorrect length")),
|
0x6700 => Err(RemoteWalletError::Protocol("Incorrect length")),
|
||||||
|
0x6802 => Err(RemoteWalletError::Protocol("Invalid parameter")),
|
||||||
|
0x6803 => Err(RemoteWalletError::Protocol(
|
||||||
|
"Overflow: message longer than MAX_MESSAGE_LENGTH",
|
||||||
|
)),
|
||||||
0x6982 => Err(RemoteWalletError::Protocol(
|
0x6982 => Err(RemoteWalletError::Protocol(
|
||||||
"Security status not satisfied (Canceled by user)",
|
"Security status not satisfied (Canceled by user)",
|
||||||
)),
|
)),
|
||||||
|
@ -361,16 +365,20 @@ pub fn is_valid_ledger(vendor_id: u16, product_id: u16) -> bool {
|
||||||
fn extend_and_serialize(derivation_path: &DerivationPath) -> Vec<u8> {
|
fn extend_and_serialize(derivation_path: &DerivationPath) -> Vec<u8> {
|
||||||
let byte = if derivation_path.change.is_some() {
|
let byte = if derivation_path.change.is_some() {
|
||||||
4
|
4
|
||||||
} else {
|
} else if derivation_path.account.is_some() {
|
||||||
3
|
3
|
||||||
|
} else {
|
||||||
|
2
|
||||||
};
|
};
|
||||||
let mut concat_derivation = vec![byte];
|
let mut concat_derivation = vec![byte];
|
||||||
concat_derivation.extend_from_slice(&SOL_DERIVATION_PATH_BE);
|
concat_derivation.extend_from_slice(&SOL_DERIVATION_PATH_BE);
|
||||||
concat_derivation.extend_from_slice(&[0x80, 0]);
|
if let Some(account) = derivation_path.account {
|
||||||
concat_derivation.extend_from_slice(&derivation_path.account.to_be_bytes());
|
|
||||||
if let Some(change) = derivation_path.change {
|
|
||||||
concat_derivation.extend_from_slice(&[0x80, 0]);
|
concat_derivation.extend_from_slice(&[0x80, 0]);
|
||||||
concat_derivation.extend_from_slice(&change.to_be_bytes());
|
concat_derivation.extend_from_slice(&account.to_be_bytes());
|
||||||
|
if let Some(change) = derivation_path.change {
|
||||||
|
concat_derivation.extend_from_slice(&[0x80, 0]);
|
||||||
|
concat_derivation.extend_from_slice(&change.to_be_bytes());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
concat_derivation
|
concat_derivation
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,12 +240,12 @@ impl RemoteWalletInfo {
|
||||||
coin
|
coin
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
if let Some(account) = parts.next() {
|
derivation_path.account = parts
|
||||||
derivation_path.account = account.replace("'", "").parse::<u16>().unwrap();
|
.next()
|
||||||
derivation_path.change = parts
|
.and_then(|account| account.replace("'", "").parse::<u16>().ok());
|
||||||
.next()
|
derivation_path.change = parts
|
||||||
.and_then(|change| change.replace("'", "").parse::<u16>().ok());
|
.next()
|
||||||
}
|
.and_then(|change| change.replace("'", "").parse::<u16>().ok());
|
||||||
} else {
|
} else {
|
||||||
return Err(RemoteWalletError::InvalidDerivationPath(
|
return Err(RemoteWalletError::InvalidDerivationPath(
|
||||||
"Derivation path too short, missing coin number".to_string(),
|
"Derivation path too short, missing coin number".to_string(),
|
||||||
|
@ -273,18 +273,23 @@ impl RemoteWalletInfo {
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Clone)]
|
#[derive(Default, PartialEq, Clone)]
|
||||||
pub struct DerivationPath {
|
pub struct DerivationPath {
|
||||||
pub account: u16,
|
pub account: Option<u16>,
|
||||||
pub change: Option<u16>,
|
pub change: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for DerivationPath {
|
impl fmt::Debug for DerivationPath {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let account = if let Some(account) = self.account {
|
||||||
|
format!("/{:?}'", account)
|
||||||
|
} else {
|
||||||
|
"".to_string()
|
||||||
|
};
|
||||||
let change = if let Some(change) = self.change {
|
let change = if let Some(change) = self.change {
|
||||||
format!("/{:?}'", change)
|
format!("/{:?}'", change)
|
||||||
} else {
|
} else {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
};
|
};
|
||||||
write!(f, "m/44'/501'/{:?}'{}", self.account, change)
|
write!(f, "m/44'/501'{}{}", account, change)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +333,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_path,
|
derivation_path,
|
||||||
DerivationPath {
|
DerivationPath {
|
||||||
account: 1,
|
account: Some(1),
|
||||||
change: Some(2),
|
change: Some(2),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -344,7 +349,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_path,
|
derivation_path,
|
||||||
DerivationPath {
|
DerivationPath {
|
||||||
account: 1,
|
account: Some(1),
|
||||||
change: Some(2),
|
change: Some(2),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue