Skip to content

Feature/trezor reconnect #1874

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open

Feature/trezor reconnect #1874

wants to merge 9 commits into from

Conversation

OBorce
Copy link
Contributor

@OBorce OBorce commented Jan 30, 2025

If the trezor device returns an USB IO error it might mean that the trezor device has been disconnected, in that case try to reconnect to the device and try the failed operation again.

@OBorce OBorce force-pushed the feature/trezor-recconect branch 2 times, most recently from 4f6708d to e0f00b5 Compare January 31, 2025 07:32
@OBorce OBorce force-pushed the refactor/wallet-generic-signer branch from 69592f8 to f16c3e3 Compare February 3, 2025 10:47
Copy link
Member

@azarovh azarovh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a rebase

@OBorce OBorce force-pushed the feature/trezor-recconect branch 2 times, most recently from 8a33777 to f8578ef Compare February 3, 2025 16:46
Err(trezor_client::Error::TransportSendMessage(
trezor_client::transport::error::Error::Usb(rusb::Error::Io),
)) => {
let (mut new_client, data) = find_trezor_device()?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling find_trezor_device on each operation is not a great idea. What if another device is returned?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we check the public keys again, and if it is a different device we error out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we check the public keys again, and if it is a different device we error out.

I understand this, the point was that it looks conceptually wrong.

Currently, the question is why do we need it if you already call init_device every time. Can't it recover the session after a usb error?

And even if it can't, calling find_trezor_device still seems wrong. Perhaps then you should split find_trezor_device into 2 functions - the "find" part and the "connect" part, so that the former is still called only once.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps then you should split find_trezor_device into 2 functions - the "find" part and the "connect" part, so that the former is still called only once.

I guess having a separate "connect" part won't be possible, because AvailableDevice is non-copyable. So we'll have to stick to calling find_trezor_device again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the question is why do we need it if you already call init_device every time. Can't it recover the session after a usb error?

Mainly for the case if the USB device disconnects for whatever reason.

Comment on lines 159 to 194
Err(trezor_client::Error::TransportSendMessage(
trezor_client::transport::error::Error::Usb(rusb::Error::Io),
)) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO instead of calling the operation and then checking for error we should just unconditionally call Trezor::initialize, passing to it the previosly obtained session_id (it's inside features). At least this is recommended in the docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added an init_device(session_id) call which internally calls initialize before each operation.

@OBorce OBorce force-pushed the refactor/wallet-generic-signer branch 2 times, most recently from 82b71a8 to c9c1c91 Compare February 25, 2025 07:54
@OBorce OBorce closed this Feb 25, 2025
@OBorce OBorce force-pushed the feature/trezor-recconect branch from f8578ef to c9c1c91 Compare February 25, 2025 11:20
@OBorce OBorce reopened this Feb 25, 2025
@OBorce OBorce force-pushed the feature/trezor-recconect branch 2 times, most recently from 2df0787 to cf6ce8c Compare February 26, 2025 12:35
@OBorce OBorce force-pushed the refactor/wallet-generic-signer branch from 48716c3 to 67609d5 Compare February 28, 2025 08:15
@OBorce OBorce force-pushed the feature/trezor-recconect branch from cf6ce8c to 66a4f17 Compare February 28, 2025 08:55
@OBorce OBorce force-pushed the refactor/wallet-generic-signer branch from 67609d5 to 220ace1 Compare February 28, 2025 09:58
Base automatically changed from refactor/wallet-generic-signer to master March 3, 2025 16:17
@OBorce OBorce force-pushed the feature/trezor-recconect branch 2 times, most recently from 0401329 to 001afc6 Compare March 6, 2025 06:38
@OBorce OBorce requested a review from ImplOfAnImpl March 14, 2025 03:32
Copy link
Contributor

@ImplOfAnImpl ImplOfAnImpl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is incomplete without changes to trezor_signer from #1895
I suggest moving those changes here (I mean the parts that are relevant for the "automatic" device selection), so that they can be reviewed together.

}

fn find_trezor_device() -> Result<(Trezor, TrezorData), TrezorError> {
fn find_trezor_device() -> Result<(Trezor, TrezorData, Vec<u8>), TrezorError> {
let mut devices = find_devices(false)
.into_iter()
.filter(|device| device.model == Model::Trezor || device.model == Model::TrezorEmulator)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, what about TrezorLegacy aka Model One?

So, why don't we allow TrezorLegacy here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added but I don't think it is supported, when I run the emulator it doesn't list the Mintlayer compatibility so it will alwasy be filtered out in the next step.

Ok(_) => Ok(()),
// In case of a USB IO error try to reconnect, and try again
Err(trezor_client::Error::TransportSendMessage(
trezor_client::transport::error::Error::Usb(rusb::Error::Io),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried disconnecting the device physically and re-connecting it and the error I got here after that was rusb::Error::NoDevice.
So, it should be handled here as well.

I wonder if the error is device-dependent though (I use Safe 3).
Perhaps we should just catch all trezor_client::transport::error::Error::Usb errors here?

P.S. plz also update comments - you currently mention "I/O error" everywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added matching on all USB errors

Err(trezor_client::Error::TransportSendMessage(
trezor_client::transport::error::Error::Usb(rusb::Error::Io),
)) => {
let (mut new_client, data) = find_trezor_device()?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps then you should split find_trezor_device into 2 functions - the "find" part and the "connect" part, so that the former is still called only once.

I guess having a separate "connect" part won't be possible, because AvailableDevice is non-copyable. So we'll have to stick to calling find_trezor_device again.

@OBorce OBorce marked this pull request as draft March 25, 2025 10:00
@OBorce OBorce force-pushed the feature/trezor-recconect branch 3 times, most recently from 09952ef to bc2d7f8 Compare March 26, 2025 10:00
@OBorce OBorce marked this pull request as ready for review March 26, 2025 10:00
Comment on lines +233 to +246
if let Some(devices) = response.multiple_devices_available {
match devices {
wallet_rpc_lib::types::MultipleDevicesAvailable::Trezor { devices } => {
let choices = CreateWalletDeviceSelectMenu::new(
devices,
wallet_path,
CliHardwareWalletType::Trezor,
true,
);
return Ok(ConsoleCommand::ChoiceMenu(Box::new(choices)));
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether we should do the same on OpenWallet. The scenario is that the user resets their device, changing its device id. And then connects this device and another one and tries opening a previously created wallet. Currently this will fail with "multiple connected Trezor devices found".
The scenario is not very probable, but it makes sense to support it at least for completeness.

P.S. but if you do it, plz write a comment explaining why we do such things on OpenWallet, because it'll look non-obvious.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

@OBorce OBorce force-pushed the feature/trezor-recconect branch 2 times, most recently from 0ad3d75 to e8d0ed6 Compare April 1, 2025 15:06
/// Optionally specify the ID for the trezor device to connect to in case there
/// are multiple trezor devices connected at the same time.
/// If not specified and there are multiple devices connected a choice will be presented
#[arg(long, conflicts_with_all(["mnemonic", "passphrase", "whether_to_store_seed_phrase"]))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should require hardware_wallet

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in separate PR #1907

/// are multiple trezor devices connected at the same time.
/// If not specified and there are multiple devices connected a choice will be presented
#[arg(long, conflicts_with_all(["mnemonic", "passphrase", "whether_to_store_seed_phrase"]))]
trezor_device_id: Option<String>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems like this string should be either device_id or included into HardwareWalletType::Trezor. Otherwise what happens when we add new wallet type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in separate PR #1907

@OBorce OBorce force-pushed the feature/trezor-recconect branch from e8d0ed6 to 844ee5b Compare April 11, 2025 12:34
@OBorce OBorce force-pushed the feature/trezor-recconect branch from 844ee5b to 37def6a Compare April 14, 2025 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants