Skip to content

Commit 4c711b6

Browse files
committed
Add Ledger signer provider
1 parent 1ae1ecc commit 4c711b6

File tree

36 files changed

+918
-488
lines changed

36 files changed

+918
-488
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node-gui/Cargo.toml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ license.workspace = true
55
version.workspace = true
66
edition.workspace = true
77
rust-version.workspace = true
8-
authors = ["Samer Afach <samer.afach@mintlayer.org>", "Ben Marsh <benjamin.marsh@mintlayer.org>", "Enrico Rubboli <enrico.rubboli@mintlayer.org>"]
8+
authors = [
9+
"Samer Afach <samer.afach@mintlayer.org>",
10+
"Ben Marsh <benjamin.marsh@mintlayer.org>",
11+
"Enrico Rubboli <enrico.rubboli@mintlayer.org>",
12+
]
913

1014
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1115

@@ -23,7 +27,7 @@ utils = { path = "../utils" }
2327
wallet = { path = "../wallet" }
2428
wallet-controller = { path = "../wallet/wallet-controller" }
2529
wallet-types = { path = "../wallet/types" }
26-
wallet-cli-commands = { path = "../wallet/wallet-cli-commands"}
30+
wallet-cli-commands = { path = "../wallet/wallet-cli-commands" }
2731
wallet-storage = { path = "../wallet/storage" }
2832

2933
anyhow.workspace = true
@@ -42,5 +46,16 @@ tokio.workspace = true
4246
winres = "0.1"
4347

4448
[features]
45-
trezor = ["wallet-controller/trezor", "wallet-types/trezor", "wallet-cli-commands/trezor", "node-gui-backend/trezor"]
46-
default = ["trezor"]
49+
trezor = [
50+
"wallet-controller/trezor",
51+
"wallet-types/trezor",
52+
"wallet-cli-commands/trezor",
53+
"node-gui-backend/trezor",
54+
]
55+
ledger = [
56+
"wallet-controller/ledger",
57+
"wallet-types/ledger",
58+
"wallet-cli-commands/ledger",
59+
"node-gui-backend/ledger",
60+
]
61+
default = ["trezor", "ledger"]

node-gui/backend/Cargo.toml

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ license.workspace = true
55
version.workspace = true
66
edition.workspace = true
77
rust-version.workspace = true
8-
authors = ["Samer Afach <samer.afach@mintlayer.org>", "Ben Marsh <benjamin.marsh@mintlayer.org>", "Enrico Rubboli <enrico.rubboli@mintlayer.org>"]
8+
authors = [
9+
"Samer Afach <samer.afach@mintlayer.org>",
10+
"Ben Marsh <benjamin.marsh@mintlayer.org>",
11+
"Enrico Rubboli <enrico.rubboli@mintlayer.org>",
12+
]
913

1014
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1115

@@ -24,9 +28,9 @@ utils = { path = "../../utils" }
2428
wallet = { path = "../../wallet" }
2529
wallet-controller = { path = "../../wallet/wallet-controller" }
2630
wallet-types = { path = "../../wallet/types" }
27-
wallet-rpc-lib = { path = "../../wallet/wallet-rpc-lib"}
28-
wallet-rpc-client = { path = "../../wallet/wallet-rpc-client"}
29-
wallet-cli-commands = { path = "../../wallet/wallet-cli-commands"}
31+
wallet-rpc-lib = { path = "../../wallet/wallet-rpc-lib" }
32+
wallet-rpc-client = { path = "../../wallet/wallet-rpc-client" }
33+
wallet-cli-commands = { path = "../../wallet/wallet-cli-commands" }
3034

3135
anyhow.workspace = true
3236
chrono.workspace = true
@@ -45,4 +49,19 @@ test-utils = { path = "../../test-utils" }
4549
rstest.workspace = true
4650

4751
[features]
48-
trezor = ["wallet/trezor", "wallet-controller/trezor", "wallet-types/trezor", "wallet-rpc-lib/trezor", "wallet-rpc-client/trezor", "wallet-cli-commands/trezor"]
52+
trezor = [
53+
"wallet/trezor",
54+
"wallet-controller/trezor",
55+
"wallet-types/trezor",
56+
"wallet-rpc-lib/trezor",
57+
"wallet-rpc-client/trezor",
58+
"wallet-cli-commands/trezor",
59+
]
60+
ledger = [
61+
"wallet/ledger",
62+
"wallet-controller/ledger",
63+
"wallet-types/ledger",
64+
"wallet-rpc-lib/ledger",
65+
"wallet-rpc-client/ledger",
66+
"wallet-cli-commands/ledger",
67+
]

node-gui/src/main_window/main_widget/tabs/wallet/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ impl Tab for WalletTab {
471471
Some(wallet_info) => match wallet_info.extra_info {
472472
wallet_controller::types::WalletExtraInfo::SoftwareWallet => "Software wallet",
473473
wallet_controller::types::WalletExtraInfo::TrezorWallet { .. } => "Trezor wallet",
474+
wallet_controller::types::WalletExtraInfo::LedgerWallet { .. } => "Ledger wallet",
474475
},
475476
None => "No wallet",
476477
};

node-gui/src/main_window/main_widget/tabs/wallet/status_bar.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16+
#[cfg(any(feature = "trezor", feature = "ledger"))]
17+
use iced::widget::{rich_text, span};
1618
use iced::{
1719
font,
1820
widget::{container, row, Container},
@@ -31,7 +33,7 @@ const HORIZONTAL_PADDING: f32 = 10.;
3133
pub fn estimate_status_bar_height(wallet_info: &WalletExtraInfo) -> f32 {
3234
match wallet_info {
3335
WalletExtraInfo::SoftwareWallet => 0.,
34-
WalletExtraInfo::TrezorWallet { .. } => {
36+
WalletExtraInfo::TrezorWallet { .. } | WalletExtraInfo::LedgerWallet { .. } => {
3537
TEXT_SIZE + 2. * VERTICAL_PADDING
3638
// For some reason, the status bar gets a bit of additional height.
3739
+ 4.
@@ -55,8 +57,6 @@ pub fn view_status_bar(wallet_info: &WalletExtraInfo) -> Option<Element<'static,
5557
device_name,
5658
firmware_version,
5759
} => {
58-
use iced::widget::{rich_text, span};
59-
6060
row![
6161
rich_text([span("Device name: ").font(bold_font), span(device_name.clone())])
6262
.size(TEXT_SIZE),
@@ -67,6 +67,11 @@ pub fn view_status_bar(wallet_info: &WalletExtraInfo) -> Option<Element<'static,
6767
.size(TEXT_SIZE),
6868
]
6969
}
70+
#[cfg(feature = "ledger")]
71+
WalletExtraInfo::LedgerWallet { app_version } => {
72+
row![rich_text([span("App version: ").font(bold_font), span(app_version.clone())])
73+
.size(TEXT_SIZE),]
74+
}
7075
};
7176

7277
let status_bar = Container::new(

wallet/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ bip39 = { workspace = true, default-features = false, features = [
3232
"std",
3333
"zeroize",
3434
] }
35+
derive_more.workspace = true
3536
hex.workspace = true
3637
itertools.workspace = true
3738
parity-scale-codec.workspace = true

wallet/src/key_chain/master_key_chain/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crypto::vrf::ExtendedVRFPrivateKey;
2222
use std::sync::Arc;
2323
use wallet_storage::{
2424
StoreTxRwUnlocked, WalletStorageReadLocked, WalletStorageReadUnlocked,
25-
WalletStorageWriteUnlocked,
25+
WalletStorageWriteLocked, WalletStorageWriteUnlocked,
2626
};
2727
use wallet_types::seed_phrase::{SerializableSeedPhrase, StoreSeedPhrase};
2828

@@ -131,7 +131,7 @@ impl MasterKeyChain {
131131

132132
pub fn create_account_key_chain(
133133
&self,
134-
db_tx: &mut impl WalletStorageWriteUnlocked,
134+
db_tx: &mut (impl WalletStorageWriteLocked + WalletStorageReadUnlocked),
135135
account_index: U31,
136136
lookahead_size: u32,
137137
) -> KeyChainResult<AccountKeyChainImplSoftware> {

wallet/src/signer/ledger_signer/ledger_messages.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,15 @@ use crypto::key::{
3030
};
3131
use serialization::{Decode, DecodeAll, Encode};
3232
use utils::ensure;
33+
use wallet_types::hw_data::LedgerFullInfo;
3334

3435
use ledger_lib::Exchange;
3536
use mintlayer_ledger_messages::{
3637
decode_all as ledger_decode_all, encode as ledger_encode, AddrType, Amount as LAmount,
3738
Bip32Path as LedgerBip32Path, CoinType, InputAdditionalInfoReq, Ins,
3839
OutputValue as LOutputValue, P1SignTx, PubKeyP1, PublicKeyReq, SignMessageReq, SignTxReq,
3940
TxInput as LTxInput, TxInputReq, TxMetadataReq, TxOutput as LTxOutput, TxOutputReq, APDU_CLASS,
40-
H256 as LH256, P1_APP_NAME, P1_SIGN_NEXT, P1_SIGN_START, P2_DONE, P2_SIGN_MORE,
41+
H256 as LH256, P1_APP_NAME, P1_GET_VERSION, P1_SIGN_NEXT, P1_SIGN_START, P2_DONE, P2_SIGN_MORE,
4142
};
4243

4344
const MAX_ADPU_LEN: usize = (u8::MAX - 5) as usize; // 4 bytes for the header + 1 for len
@@ -136,11 +137,15 @@ pub async fn sign_challenge<L: Exchange>(
136137

137138
pub async fn get_app_name<L: Exchange>(ledger: &mut L) -> Result<Vec<u8>, ledger_lib::Error> {
138139
let msg_buf = [APDU_CLASS, Ins::APP_NAME, P1_APP_NAME, P2_DONE];
139-
ledger.exchange(&msg_buf, Duration::from_millis(100)).await
140+
ledger.exchange(&msg_buf, Duration::from_millis(500)).await
140141
}
141142

142-
#[allow(dead_code)]
143-
pub async fn check_current_app<L: Exchange>(ledger: &mut L) -> SignerResult<()> {
143+
async fn get_app_version<L: Exchange>(ledger: &mut L) -> Result<Vec<u8>, ledger_lib::Error> {
144+
let msg_buf = [APDU_CLASS, Ins::GET_VERSION, P1_GET_VERSION, P2_DONE];
145+
ledger.exchange(&msg_buf, Duration::from_millis(500)).await
146+
}
147+
148+
pub async fn check_current_app<L: Exchange>(ledger: &mut L) -> SignerResult<LedgerFullInfo> {
144149
let resp = get_app_name(ledger)
145150
.await
146151
.map_err(|err| LedgerError::DeviceError(err.to_string()))?;
@@ -152,7 +157,20 @@ pub async fn check_current_app<L: Exchange>(ledger: &mut L) -> SignerResult<()>
152157
LedgerError::DifferentActiveApp(name)
153158
);
154159

155-
Ok(())
160+
let resp = get_app_version(ledger)
161+
.await
162+
.map_err(|err| LedgerError::DeviceError(err.to_string()))?;
163+
let ver = ok_response(resp)?;
164+
let app_version = match ver.as_slice() {
165+
[major, minor, patch] => common::primitives::semver::SemVer {
166+
major: *major,
167+
minor: *minor,
168+
patch: *patch as u16,
169+
},
170+
_ => return Err(SignerError::LedgerError(LedgerError::InvalidResponse)),
171+
};
172+
173+
Ok(LedgerFullInfo { app_version })
156174
}
157175

158176
pub async fn get_extended_public_key<L: Exchange>(

0 commit comments

Comments
 (0)