Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions mm2src/coins/coin_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,27 @@ pub mod common_impl {
params.min_addresses_number.max(Some(path_to_address.address_id + 1)),
)
.await?;
drop(new_account);

if coin.is_trezor() {
let enabled_address =
hd_wallet
.get_enabled_address()
.await
.ok_or(EnableCoinBalanceError::NewAddressDerivingError(
NewAddressDerivingError::Internal(
"Couldn't find enabled address after it has already been enabled".to_string(),
),
))?;
coin.received_enabled_address_from_hw_wallet(enabled_address)
.await
.map_err(|e| {
EnableCoinBalanceError::NewAddressDerivingError(NewAddressDerivingError::Internal(format!(
"Coin rejected the enabled address derived from the hardware wallet: {}",
e
)))
})?;
Comment on lines +511 to +528
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This code is repeated, you can refactor it in the other open PR as I am gonna merge this now

}
// Todo: The enabled address should be indicated in the response.
result.accounts.push(account_balance);
return Ok(result);
Expand Down Expand Up @@ -538,6 +559,27 @@ pub mod common_impl {
.await?;
result.accounts.push(account_balance);
}
drop(accounts);

if coin.is_trezor() {
let enabled_address =
hd_wallet
.get_enabled_address()
.await
.ok_or(EnableCoinBalanceError::NewAddressDerivingError(
NewAddressDerivingError::Internal(
"Couldn't find enabled address after it has already been enabled".to_string(),
),
))?;
coin.received_enabled_address_from_hw_wallet(enabled_address)
.await
.map_err(|e| {
EnableCoinBalanceError::NewAddressDerivingError(NewAddressDerivingError::Internal(format!(
"Coin rejected the enabled address derived from the hardware wallet: {}",
e
)))
})?;
}

Ok(result)
}
Expand Down
12 changes: 11 additions & 1 deletion mm2src/coins/hd_wallet/coin_ops.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{inner_impl, AccountUpdatingError, AddressDerivingError, DisplayAddress, ExtendedPublicKeyOps,
HDAccountOps, HDCoinExtendedPubkey, HDCoinHDAccount, HDCoinHDAddress, HDConfirmAddress, HDWalletOps,
NewAddressDeriveConfirmError, NewAddressDerivingError};
use crate::hd_wallet::{HDAddressOps, HDWalletStorageOps, TrezorCoinError};
use crate::hd_wallet::{errors::SettingEnabledAddressError, HDAddressOps, HDWalletStorageOps, TrezorCoinError};
use async_trait::async_trait;
use bip32::{ChildNumber, DerivationPath};
use crypto::Bip44Chain;
Expand Down Expand Up @@ -231,4 +231,14 @@ pub trait HDWalletCoinOps {

/// Returns the Trezor coin name for this coin.
fn trezor_coin(&self) -> MmResult<String, TrezorCoinError>;

/// Informs the coin of the enabled address provided/derived by the hardware wallet.
async fn received_enabled_address_from_hw_wallet(
Comment on lines +235 to +236
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I would prefer to have this in a separate trait in the future to start separating specific HW wallet code from the more general HD wallet code. This is not at all a priority at the current stage but we need it mentioned somewhere in our issues / checklists or at least a todo.

&self,
_enabled_address: HDCoinHDAddress<Self>,
) -> MmResult<(), SettingEnabledAddressError> {
// By default, the default implementation is doing nothing.
// Different coins can use this hook to perform additional actions if needed.
Ok(())
}
}
5 changes: 5 additions & 0 deletions mm2src/coins/hd_wallet/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,8 @@ impl From<TrezorCoinError> for NewAddressDeriveConfirmError {
NewAddressDeriveConfirmError::DeriveError(NewAddressDerivingError::Internal(e.to_string()))
}
}

#[derive(Display)]
pub enum SettingEnabledAddressError {
Internal(String),
}
2 changes: 1 addition & 1 deletion mm2src/coins/hd_wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub use confirm_address::{HDConfirmAddress, HDConfirmAddressError};
mod errors;
pub use errors::{AccountUpdatingError, AddressDerivingError, HDExtractPubkeyError, HDWithdrawError,
InvalidBip44ChainError, NewAccountCreationError, NewAddressDeriveConfirmError,
NewAddressDerivingError, TrezorCoinError};
NewAddressDerivingError, SettingEnabledAddressError, TrezorCoinError};

mod pubkey;
pub use pubkey::{ExtendedPublicKeyOps, ExtractExtendedPubkey, HDXPubExtractor, RpcTaskXPubExtractor};
Expand Down
12 changes: 11 additions & 1 deletion mm2src/coins/utxo/bch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use super::*;
use crate::coin_balance::{EnableCoinBalanceError, HDAddressBalance, HDWalletBalance, HDWalletBalanceOps};
use crate::coin_errors::{AddressFromPubkeyError, MyAddressError, ValidatePaymentResult};
use crate::hd_wallet::{ExtractExtendedPubkey, HDAddressSelector, HDCoinAddress, HDCoinWithdrawOps,
HDExtractPubkeyError, HDXPubExtractor, TrezorCoinError, WithdrawSenderAddress};
HDExtractPubkeyError, HDXPubExtractor, SettingEnabledAddressError, TrezorCoinError,
WithdrawSenderAddress};
use crate::my_tx_history_v2::{CoinWithTxHistoryV2, MyTxHistoryErrorV2, MyTxHistoryTarget, TxDetailsBuilder,
TxHistoryStorage};
use crate::tx_history_storage::{GetTxHistoryFilters, WalletId};
Expand Down Expand Up @@ -1388,6 +1389,15 @@ impl HDWalletCoinOps for BchCoin {
}

fn trezor_coin(&self) -> MmResult<String, TrezorCoinError> { utxo_common::trezor_coin(self) }

async fn received_enabled_address_from_hw_wallet(
&self,
enabled_address: UtxoHDAddress,
) -> MmResult<(), SettingEnabledAddressError> {
utxo_common::received_enabled_address_from_hw_wallet(self, enabled_address.address)
.await
.mm_err(SettingEnabledAddressError::Internal)
}
}

impl HDCoinWithdrawOps for BchCoin {}
Expand Down
12 changes: 11 additions & 1 deletion mm2src/coins/utxo/qtum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::coin_balance::{self, EnableCoinBalanceError, EnabledCoinBalanceParams
HDWalletBalance, HDWalletBalanceOps};
use crate::coin_errors::{AddressFromPubkeyError, MyAddressError, ValidatePaymentResult};
use crate::hd_wallet::{ExtractExtendedPubkey, HDAddressSelector, HDCoinAddress, HDCoinWithdrawOps, HDConfirmAddress,
HDExtractPubkeyError, HDXPubExtractor, TrezorCoinError, WithdrawSenderAddress};
HDExtractPubkeyError, HDXPubExtractor, SettingEnabledAddressError, TrezorCoinError,
WithdrawSenderAddress};
use crate::my_tx_history_v2::{CoinWithTxHistoryV2, MyTxHistoryErrorV2, MyTxHistoryTarget, TxHistoryStorage};
use crate::rpc_command::account_balance::{self, AccountBalanceParams, AccountBalanceRpcOps, HDAccountBalanceResponse};
use crate::rpc_command::get_new_address::{self, GetNewAddressParams, GetNewAddressResponse, GetNewAddressRpcError,
Expand Down Expand Up @@ -1036,6 +1037,15 @@ impl HDWalletCoinOps for QtumCoin {
}

fn trezor_coin(&self) -> MmResult<String, TrezorCoinError> { utxo_common::trezor_coin(self) }

async fn received_enabled_address_from_hw_wallet(
&self,
enabled_address: UtxoHDAddress,
) -> MmResult<(), SettingEnabledAddressError> {
utxo_common::received_enabled_address_from_hw_wallet(self, enabled_address.address)
.await
.mm_err(SettingEnabledAddressError::Internal)
}
}

impl HDCoinWithdrawOps for QtumCoin {}
Expand Down
10 changes: 3 additions & 7 deletions mm2src/coins/utxo/utxo_builder/utxo_coin_builder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::hd_wallet::{load_hd_accounts_from_storage, HDAccountsMutex, HDWallet, HDWalletCoinStorage, HDWalletOps,
use crate::hd_wallet::{load_hd_accounts_from_storage, HDAccountsMutex, HDWallet, HDWalletCoinStorage,
HDWalletStorageError, DEFAULT_GAP_LIMIT};
use crate::utxo::rpc_clients::{ElectrumClient, ElectrumClientSettings, ElectrumConnectionSettings, EstimateFeeMethod,
UtxoRpcClientEnum};
Expand Down Expand Up @@ -321,12 +321,8 @@ pub trait UtxoFieldsWithHardwareWalletBuilder: UtxoCoinBuilderCommonOps {
address_format,
};

let my_address = hd_wallet
.get_enabled_address()
.await
.ok_or_else(|| UtxoCoinBuildError::Internal("Failed to get enabled address from HD wallet".to_owned()))?;
let my_script_pubkey = output_script(&my_address.address).map(|script| script.to_bytes())?;
let recently_spent_outpoints = AsyncMutex::new(RecentlySpentOutPoints::new(my_script_pubkey));
// TODO: Creating a dummy output script for now. We better set it to the enabled address output script.
let recently_spent_outpoints = AsyncMutex::new(RecentlySpentOutPoints::new(Default::default()));

// Create an abortable system linked to the `MmCtx` so if the context is stopped via `MmArc::stop`,
// all spawned futures related to this `UTXO` coin will be aborted as well.
Expand Down
21 changes: 21 additions & 0 deletions mm2src/coins/utxo/utxo_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,27 @@ where
})
}

pub(crate) async fn received_enabled_address_from_hw_wallet<Coin>(
coin: &Coin,
enabled_address: Address,
) -> MmResult<(), String>
where
Coin: AsRef<UtxoCoinFields>,
{
let my_script_pubkey = match output_script(&enabled_address) {
Ok(script) => script.to_bytes(),
Err(e) => {
return MmError::err(format!(
"Error generating the output_script for the enabled_address={}: {}",
enabled_address, e
));
},
};
let mut recently_spent_outputs = coin.as_ref().recently_spent_outpoints.lock().await;
*recently_spent_outputs = RecentlySpentOutPoints::new(my_script_pubkey);
Ok(())
}

pub async fn produce_hd_address_scanner<T>(coin: &T) -> BalanceResult<UtxoAddressScanner>
where
T: AsRef<UtxoCoinFields>,
Expand Down
12 changes: 11 additions & 1 deletion mm2src/coins/utxo/utxo_standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::coin_balance::{self, EnableCoinBalanceError, EnabledCoinBalanceParams
HDWalletBalance, HDWalletBalanceOps};
use crate::coin_errors::{AddressFromPubkeyError, MyAddressError, ValidatePaymentResult};
use crate::hd_wallet::{ExtractExtendedPubkey, HDAddressSelector, HDCoinAddress, HDCoinWithdrawOps, HDConfirmAddress,
HDExtractPubkeyError, HDXPubExtractor, TrezorCoinError, WithdrawSenderAddress};
HDExtractPubkeyError, HDXPubExtractor, SettingEnabledAddressError, TrezorCoinError,
WithdrawSenderAddress};
use crate::my_tx_history_v2::{CoinWithTxHistoryV2, MyTxHistoryErrorV2, MyTxHistoryTarget, TxHistoryStorage};
use crate::rpc_command::account_balance::{self, AccountBalanceParams, AccountBalanceRpcOps, HDAccountBalanceResponse};
use crate::rpc_command::get_new_address::{self, GetNewAddressParams, GetNewAddressResponse, GetNewAddressRpcError,
Expand Down Expand Up @@ -1123,6 +1124,15 @@ impl HDWalletCoinOps for UtxoStandardCoin {
}

fn trezor_coin(&self) -> MmResult<String, TrezorCoinError> { utxo_common::trezor_coin(self) }

async fn received_enabled_address_from_hw_wallet(
&self,
enabled_address: UtxoHDAddress,
) -> MmResult<(), SettingEnabledAddressError> {
utxo_common::received_enabled_address_from_hw_wallet(self, enabled_address.address)
.await
.mm_err(SettingEnabledAddressError::Internal)
}
}

impl HDCoinWithdrawOps for UtxoStandardCoin {}
Expand Down
Loading