Skip to content

Commit 0d5722a

Browse files
committed
save trezor device id and label and compare on startup
1 parent 392cc14 commit 0d5722a

File tree

10 files changed

+115
-15
lines changed

10 files changed

+115
-15
lines changed

wallet/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,3 @@ tempfile.workspace = true
4545
[features]
4646
trezor = ["dep:trezor-client", "wallet-types/trezor"]
4747
trezor-emulator = []
48-
49-
default = ["trezor"]

wallet/src/signer/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ use wallet_storage::{
3737
WalletStorageReadLocked, WalletStorageReadUnlocked, WalletStorageWriteUnlocked,
3838
};
3939
use wallet_types::{
40-
partially_signed_transaction::PartiallySignedTransaction, signature_status::SignatureStatus,
41-
AccountId,
40+
hw_data::HardwareWalletData, partially_signed_transaction::PartiallySignedTransaction,
41+
signature_status::SignatureStatus, AccountId,
4242
};
4343

4444
use crate::{
@@ -156,4 +156,6 @@ pub trait SignerProvider {
156156
db_tx: &impl WalletStorageReadLocked,
157157
id: &AccountId,
158158
) -> WalletResult<Account<Self::K>>;
159+
160+
fn get_hardware_wallet_data(&mut self) -> Option<HardwareWalletData>;
159161
}

wallet/src/signer/software_signer/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ use wallet_storage::{
4848
WalletStorageWriteUnlocked,
4949
};
5050
use wallet_types::{
51-
partially_signed_transaction::PartiallySignedTransaction, seed_phrase::StoreSeedPhrase,
52-
signature_status::SignatureStatus, AccountId,
51+
hw_data::HardwareWalletData, partially_signed_transaction::PartiallySignedTransaction,
52+
seed_phrase::StoreSeedPhrase, signature_status::SignatureStatus, AccountId,
5353
};
5454

5555
use crate::{
@@ -480,6 +480,10 @@ impl SignerProvider for SoftwareSignerProvider {
480480
) -> WalletResult<Account<Self::K>> {
481481
Account::load_from_database(chain_config, db_tx, id)
482482
}
483+
484+
fn get_hardware_wallet_data(&mut self) -> Option<HardwareWalletData> {
485+
None
486+
}
483487
}
484488

485489
#[cfg(test)]

wallet/src/signer/trezor_signer/mod.rs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ use wallet_storage::{
8484
};
8585
use wallet_types::{
8686
account_info::DEFAULT_ACCOUNT_INDEX,
87+
hw_data::{HardwareWalletData, TrezorData},
8788
partially_signed_transaction::{
8889
OrderAdditionalInfo, PartiallySignedTransaction, TokenAdditionalInfo, TxAdditionalInfo,
8990
},
@@ -1133,6 +1134,7 @@ fn to_trezor_output_lock(lock: &OutputTimeLock) -> trezor_client::protos::Mintla
11331134
#[derive(Clone)]
11341135
pub struct TrezorSignerProvider {
11351136
client: Arc<Mutex<Trezor>>,
1137+
data: TrezorData,
11361138
}
11371139

11381140
impl std::fmt::Debug for TrezorSignerProvider {
@@ -1143,22 +1145,24 @@ impl std::fmt::Debug for TrezorSignerProvider {
11431145

11441146
impl TrezorSignerProvider {
11451147
pub fn new() -> Result<Self, TrezorError> {
1146-
let client =
1148+
let (client, data) =
11471149
find_trezor_device().map_err(|err| TrezorError::DeviceError(err.to_string()))?;
11481150

11491151
Ok(Self {
11501152
client: Arc::new(Mutex::new(client)),
1153+
data,
11511154
})
11521155
}
11531156

11541157
pub fn load_from_database(
11551158
chain_config: Arc<ChainConfig>,
11561159
db_tx: &impl WalletStorageReadLocked,
11571160
) -> WalletResult<Self> {
1158-
let client = find_trezor_device().map_err(SignerError::TrezorError)?;
1161+
let (client, data) = find_trezor_device().map_err(SignerError::TrezorError)?;
11591162

11601163
let provider = Self {
11611164
client: Arc::new(Mutex::new(client)),
1165+
data,
11621166
};
11631167

11641168
check_public_keys(db_tx, &provider, chain_config)?;
@@ -1219,14 +1223,34 @@ fn check_public_keys(
12191223
.ok_or(WalletError::WalletNotInitialized)?;
12201224
let expected_pk = provider.fetch_extended_pub_key(&chain_config, DEFAULT_ACCOUNT_INDEX)?;
12211225
let loaded_acc = provider.load_account_from_database(chain_config, db_tx, &first_acc)?;
1222-
ensure!(
1223-
loaded_acc.key_chain().account_public_key() == &expected_pk,
1224-
WalletError::HardwareWalletDifferentFile
1225-
);
1226-
Ok(())
1226+
1227+
if loaded_acc.key_chain().account_public_key() == &expected_pk {
1228+
return Ok(());
1229+
}
1230+
1231+
if let Some(data) = db_tx.get_hardware_wallet_data()? {
1232+
match data {
1233+
HardwareWalletData::Trezor(data) => {
1234+
// If the device_id and label are the same but public keys are different, maybe a
1235+
// different passphrase was used
1236+
if data == provider.data {
1237+
return Err(WalletError::HardwareWalletDifferentPassphrase);
1238+
} else {
1239+
return Err(WalletError::HardwareWalletDifferentDevice(
1240+
data.device_id,
1241+
provider.data.device_id.clone(),
1242+
data.label,
1243+
provider.data.label.clone(),
1244+
));
1245+
}
1246+
}
1247+
}
1248+
}
1249+
1250+
Err(WalletError::HardwareWalletDifferentFile)
12271251
}
12281252

1229-
fn find_trezor_device() -> Result<Trezor, TrezorError> {
1253+
fn find_trezor_device() -> Result<(Trezor, TrezorData), TrezorError> {
12301254
let mut devices = find_devices(false)
12311255
.into_iter()
12321256
.filter(|device| device.model == Model::Trezor || device.model == Model::TrezorEmulator)
@@ -1250,7 +1274,12 @@ fn find_trezor_device() -> Result<Trezor, TrezorError> {
12501274
TrezorError::MintlayerFeaturesNotSupported
12511275
);
12521276

1253-
Ok(client)
1277+
let data = TrezorData {
1278+
label: features.label().to_owned(),
1279+
device_id: features.device_id().to_owned(),
1280+
};
1281+
1282+
Ok((client, data))
12541283
}
12551284

12561285
impl SignerProvider for TrezorSignerProvider {
@@ -1291,6 +1320,10 @@ impl SignerProvider for TrezorSignerProvider {
12911320
) -> WalletResult<Account<Self::K>> {
12921321
Account::load_from_database(chain_config, db_tx, id)
12931322
}
1323+
1324+
fn get_hardware_wallet_data(&mut self) -> Option<HardwareWalletData> {
1325+
Some(HardwareWalletData::Trezor(self.data.clone()))
1326+
}
12941327
}
12951328

12961329
#[cfg(feature = "trezor-emulator")]

wallet/src/wallet/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ pub enum WalletError {
258258
CannotChangeTrezorWalletType,
259259
#[error("The file being loaded does not correspond to the connected hardware wallet")]
260260
HardwareWalletDifferentFile,
261+
#[error("The file being loaded does not correspond to the connected hardware wallet: File DeviceId {0}, Connected device {1}, labels {2} and {3}")]
262+
HardwareWalletDifferentDevice(String, String, String, String),
263+
#[error("The file being loaded correspond to the connected hardware wallet, but public keys are different. Maybe a wrong passphrase was inputed?")]
264+
HardwareWalletDifferentPassphrase,
261265
#[error("Missing additional data for Pool {0}")]
262266
MissingPoolAdditionalData(PoolId),
263267
#[error("Missing additional data for Token {0}")]
@@ -344,6 +348,10 @@ where
344348
db_tx.set_wallet_type(wallet_type)?;
345349
let mut signer_provider = signer_provider(&mut db_tx)?;
346350

351+
if let Some(data) = signer_provider.get_hardware_wallet_data() {
352+
db_tx.set_hardware_wallet_data(data)?;
353+
}
354+
347355
let default_account = Wallet::<B, P>::create_next_unused_account(
348356
U31::ZERO,
349357
chain_config.clone(),

wallet/storage/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ bip39 = { workspace = true, default-features = false, features = ["std", "zeroiz
2525
test-utils = { path = "../../test-utils" }
2626

2727
rstest.workspace = true
28+
29+
[features]
30+
trezor = ["wallet-types/trezor"]

wallet/storage/src/internal/store_tx.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,13 @@ use wallet_types::{
4747
AccountDerivationPathId, AccountId, AccountInfo, AccountKeyPurposeId, AccountWalletCreatedTxId,
4848
AccountWalletTxId, KeychainUsageState, WalletTx,
4949
};
50+
51+
use wallet_types::hw_data;
52+
5053
mod well_known {
5154
use common::chain::block::timestamp::BlockTimestamp;
5255
use crypto::kdf::KdfChallenge;
56+
use wallet_types::hw_data;
5357
use wallet_types::{account_info::AccountVrfKeys, chain_info::ChainInfo, wallet_type};
5458

5559
use super::Codec;
@@ -79,6 +83,7 @@ mod well_known {
7983
declare_entry!(LookaheadSize: u32);
8084
declare_entry!(LegacyVfrPubKey: AccountVrfKeys);
8185
declare_entry!(WalletType: wallet_type::WalletType);
86+
declare_entry!(HardwareWalletData: hw_data::HardwareWalletData);
8287
}
8388

8489
#[derive(PartialEq, Clone)]
@@ -337,6 +342,12 @@ macro_rules! impl_read_ops {
337342
let lookahead = self.read_value::<well_known::LookaheadSize>()?;
338343
lookahead.ok_or(crate::Error::WalletDbInconsistentState)
339344
}
345+
346+
fn get_hardware_wallet_data(
347+
&self,
348+
) -> crate::Result<Option<hw_data::HardwareWalletData>> {
349+
self.read_value::<well_known::HardwareWalletData>()
350+
}
340351
}
341352

342353
impl<'st, B: storage::Backend> $TxType<'st, B> {
@@ -600,6 +611,13 @@ macro_rules! impl_write_ops {
600611
fn set_lookahead_size(&mut self, lookahead_size: u32) -> crate::Result<()> {
601612
self.write_value::<well_known::LookaheadSize>(&lookahead_size)
602613
}
614+
615+
fn set_hardware_wallet_data(
616+
&mut self,
617+
data: hw_data::HardwareWalletData,
618+
) -> crate::Result<()> {
619+
self.write_value::<well_known::HardwareWalletData>(&data)
620+
}
603621
}
604622

605623
impl<'st, B: storage::Backend> $TxType<'st, B> {

wallet/storage/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use wallet_types::{
3535
account_id::{AccountAddress, AccountPublicKey},
3636
account_info::{AccountVrfKeys, StandaloneMultisig, StandaloneWatchOnlyKey},
3737
chain_info::ChainInfo,
38+
hw_data::HardwareWalletData,
3839
keys::RootKeys,
3940
seed_phrase::SerializableSeedPhrase,
4041
wallet_type::WalletType,
@@ -118,6 +119,7 @@ pub trait WalletStorageReadLocked {
118119
) -> Result<BTreeMap<AccountDerivationPathId, ExtendedPublicKey>>;
119120
fn get_median_time(&self) -> Result<Option<BlockTimestamp>>;
120121
fn get_lookahead_size(&self) -> Result<u32>;
122+
fn get_hardware_wallet_data(&self) -> Result<Option<HardwareWalletData>>;
121123
}
122124

123125
/// Queries on persistent wallet data with access to encrypted data
@@ -197,6 +199,7 @@ pub trait WalletStorageWriteLocked: WalletStorageReadLocked {
197199
fn set_lookahead_size(&mut self, lookahead_size: u32) -> Result<()>;
198200
fn clear_public_keys(&mut self) -> Result<()>;
199201
fn clear_addresses(&mut self) -> Result<()>;
202+
fn set_hardware_wallet_data(&mut self, data: HardwareWalletData) -> Result<()>;
200203
}
201204

202205
/// Modifying operations on persistent wallet data with access to encrypted data

wallet/types/src/hw_data.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (c) 2025 RBB S.r.l
2+
// opensource@mintlayer.org
3+
// SPDX-License-Identifier: MIT
4+
// Licensed under the MIT License;
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// https://github.com/mintlayer/mintlayer-core/blob/master/LICENSE
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
use serialization::{Decode, Encode};
17+
18+
#[cfg(feature = "trezor")]
19+
#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)]
20+
pub struct TrezorData {
21+
pub device_id: String,
22+
pub label: String,
23+
}
24+
25+
#[derive(Debug, Clone, Encode, Decode)]
26+
pub enum HardwareWalletData {
27+
#[cfg(feature = "trezor")]
28+
#[codec(index = 0)]
29+
Trezor(TrezorData),
30+
}

wallet/types/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub mod account_id;
1717
pub mod account_info;
1818
pub mod chain_info;
1919
pub mod currency;
20+
pub mod hw_data;
2021
pub mod keys;
2122
pub mod partially_signed_transaction;
2223
pub mod seed_phrase;

0 commit comments

Comments
 (0)