Skip to content
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

[r2r] Global HD account #1512

Merged
merged 32 commits into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
54f638c
Add `HdAccountCtx` to `CryptoCtx` as an alternative to `IguanaCtx`
sergeyboyko0791 Oct 22, 2022
d180072
Rename `CryptoCtx::secp256k1_pubkey*` to `CryptoCtx::mm2_internal_pub…
sergeyboyko0791 Oct 22, 2022
6621606
Remove `MmCtx::secp256k1_key_pair()`
sergeyboyko0791 Oct 24, 2022
31c36f1
Fix some TODOs
sergeyboyko0791 Oct 25, 2022
28d52d3
Add `PrivKeyBuildPolicy::GlobalHDAccount`
sergeyboyko0791 Oct 27, 2022
fc26e99
Merge branch 'dev' into mm2-hd-account
sergeyboyko0791 Oct 27, 2022
15ebe4c
Remove `MmCtx::secp256k1_key_pair`
sergeyboyko0791 Oct 27, 2022
5ea08c0
Remove unused dependencies
sergeyboyko0791 Oct 27, 2022
2d60518
Implement `CryptoCtx::init_with_global_hd_account`
sergeyboyko0791 Oct 30, 2022
a8791b5
Fix TODOs
sergeyboyko0791 Oct 30, 2022
ebcc10d
Cover `hd_account_id` with tests
sergeyboyko0791 Oct 31, 2022
8cb09d2
Fix fmt warnings
sergeyboyko0791 Oct 31, 2022
7a845f4
Fix wasm tests
sergeyboyko0791 Oct 31, 2022
137c8fe
Fix RICK-MORTY swap
sergeyboyko0791 Nov 1, 2022
e62cfdf
Fix TODOs
sergeyboyko0791 Nov 1, 2022
4477c1d
Merge branch 'dev' into mm2-hd-account
sergeyboyko0791 Nov 1, 2022
5627cde
Minor changes
sergeyboyko0791 Nov 1, 2022
2857e58
Merge branch 'dev' into mm2-hd-account
sergeyboyko0791 Nov 6, 2022
5752e52
Remove `PrivKeyBuildPolicy::GlobalHDAccount`
sergeyboyko0791 Nov 7, 2022
c607380
Merge branch 'dev' into mm2-hd-account
sergeyboyko0791 Nov 10, 2022
e7416e5
Fix PR issues
sergeyboyko0791 Nov 10, 2022
827a4f4
Use `is_my_order` within `request_and_fill_orderbook`
sergeyboyko0791 Nov 10, 2022
7b6d130
Remove `IguanaCtx`, move `secp256k1_key_pair` to `CryptoCtx`
sergeyboyko0791 Nov 10, 2022
e0c60ad
Distinguish the common implementation of `CryptoCtx` initializers
sergeyboyko0791 Nov 11, 2022
7bdbd6d
Merge branch 'dev' into mm2-hd-account
sergeyboyko0791 Nov 15, 2022
95a266e
Return PrivKeyBuildPolicy::GlobalHDAccount
sergeyboyko0791 Nov 15, 2022
2548a0e
Fix ZCoin BIP32 derivation
sergeyboyko0791 Nov 15, 2022
68db7be
Add `z_derivation_path` to `ZCoinProtocolInfo`
sergeyboyko0791 Nov 15, 2022
185f74a
Check if `BTC-segwit` derivation works
sergeyboyko0791 Nov 15, 2022
5c59055
Minor fix
sergeyboyko0791 Nov 15, 2022
1c253db
Ignore Tendermint tests
sergeyboyko0791 Nov 15, 2022
27b0928
Fix `test_withdraw_segwit`
sergeyboyko0791 Nov 15, 2022
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
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions mm2src/coins/coin_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ where
{
async fn coin_balance_report(&self) -> BalanceResult<CoinBalanceReport> {
match self.derivation_method() {
DerivationMethod::Iguana(my_address) => self
DerivationMethod::SingleAddress(my_address) => self
.my_balance()
.compat()
.await
Expand Down Expand Up @@ -176,7 +176,7 @@ where
XPubExtractor: HDXPubExtractor + Sync,
{
match self.derivation_method() {
DerivationMethod::Iguana(my_address) => self
DerivationMethod::SingleAddress(my_address) => self
.my_balance()
.compat()
.await
Expand Down
13 changes: 7 additions & 6 deletions mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ use web3_transport::{EthFeeHistoryNamespace, Web3Transport, Web3TransportNode};
use super::{coin_conf, AsyncMutex, BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, CoinFutSpawner,
CoinProtocol, CoinTransportMetrics, CoinsContext, FeeApproxStage, FoundSwapTxSpend, HistorySyncState,
MarketCoinOps, MmCoin, MyAddressError, NegotiateSwapContractAddrErr, NumConversError, NumConversResult,
PaymentInstructions, PaymentInstructionsErr, RawTransactionError, RawTransactionFut,
RawTransactionRequest, RawTransactionRes, RawTransactionResult, RpcClientType, RpcTransportEventHandler,
RpcTransportEventHandlerShared, SearchForSwapTxSpendInput, SendMakerPaymentArgs,
SendMakerRefundsPaymentArgs, SendMakerSpendsTakerPaymentArgs, SendTakerPaymentArgs,
PaymentInstructions, PaymentInstructionsErr, PrivKeyBuildPolicy, PrivKeyPolicyNotAllowed,
RawTransactionError, RawTransactionFut, RawTransactionRequest, RawTransactionRes, RawTransactionResult,
RpcClientType, RpcTransportEventHandler, RpcTransportEventHandlerShared, SearchForSwapTxSpendInput,
SendMakerPaymentArgs, SendMakerRefundsPaymentArgs, SendMakerSpendsTakerPaymentArgs, SendTakerPaymentArgs,
SendTakerRefundsPaymentArgs, SendTakerSpendsMakerPaymentArgs, SignatureError, SignatureResult, SwapOps,
TradeFee, TradePreimageError, TradePreimageFut, TradePreimageResult, TradePreimageValue, Transaction,
TransactionDetails, TransactionEnum, TransactionErr, TransactionFut, TxMarshalingErr,
Expand All @@ -80,6 +80,7 @@ pub use rlp;
mod web3_transport;

#[path = "eth/v2_activation.rs"] pub mod v2_activation;
use v2_activation::key_pair_from_priv_key_policy;

/// https://github.com/artemii235/etomic-swap/blob/master/contracts/EtomicSwap.sol
/// Dev chain (195.201.0.6:8565) contract address: 0xa09ad3cd7e96586ebd05a2607ee56b56fb2db8fd
Expand Down Expand Up @@ -3579,8 +3580,8 @@ pub async fn eth_coin_from_conf_and_request(
ticker: &str,
conf: &Json,
req: &Json,
priv_key: &[u8],
protocol: CoinProtocol,
priv_key_policy: PrivKeyBuildPolicy,
) -> Result<EthCoin, String> {
let mut urls: Vec<String> = try_s!(json::from_value(req["urls"].clone()));
if urls.is_empty() {
Expand Down Expand Up @@ -3610,7 +3611,7 @@ pub async fn eth_coin_from_conf_and_request(
}
}

let key_pair: KeyPair = try_s!(KeyPair::from_secret_slice(priv_key));
let key_pair = try_s!(key_pair_from_priv_key_policy(conf, priv_key_policy));
let my_address = key_pair.address();

let mut web3_instances = vec![];
Expand Down
8 changes: 5 additions & 3 deletions mm2src/coins/eth/eth_tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
use crate::IguanaPrivKey;
use common::block_on;
use mm2_core::mm_ctx::{MmArc, MmCtxBuilder};
use mm2_test_helpers::for_tests::{ETH_MAINNET_NODE, ETH_MAINNET_SWAP_CONTRACT};
Expand Down Expand Up @@ -1230,14 +1231,14 @@ fn polygon_check_if_my_payment_sent() {
"swap_contract_address": "0x9130b257d37a52e52f21054c4da3450c72f595ce",
});

let priv_key = [1; 32];
let priv_key_policy = PrivKeyBuildPolicy::IguanaPrivKey(IguanaPrivKey::from([1; 32]));
let coin = block_on(eth_coin_from_conf_and_request(
&ctx,
"MATIC",
&conf,
&request,
&priv_key,
CoinProtocol::ETH,
priv_key_policy,
))
.unwrap();

Expand Down Expand Up @@ -1445,13 +1446,14 @@ fn test_eth_validate_valid_and_invalid_pubkey() {
3, 98, 177, 3, 108, 39, 234, 144, 131, 178, 103, 103, 127, 80, 230, 166, 53, 68, 147, 215, 42, 216, 144, 72,
172, 110, 180, 13, 123, 179, 10, 49,
];
let priv_key_policy = PrivKeyBuildPolicy::IguanaPrivKey(IguanaPrivKey::from(priv_key));
let coin = block_on(eth_coin_from_conf_and_request(
&ctx,
"MATIC",
&conf,
&request,
&priv_key,
CoinProtocol::ETH,
priv_key_policy,
))
.unwrap();
// Test expected to pass at this point as we're using a valid pubkey to validate against a valid pubkey
Expand Down
39 changes: 35 additions & 4 deletions mm2src/coins/eth/v2_activation.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::*;
use common::executor::AbortedError;
use crypto::StandardHDPathToCoin;

#[derive(Display, Serialize, SerializeErrorType)]
#[serde(tag = "error_type", content = "error_data")]
Expand All @@ -16,6 +17,11 @@ pub enum EthActivationV2Error {
UnreachableNodes(String),
#[display(fmt = "Enable request for ETH coin must have at least 1 node")]
AtLeastOneNodeRequired,
#[display(fmt = "'derivation_path' field is not found in config")]
DerivationPathIsNotSet,
#[display(fmt = "Error deserializing 'derivation_path': {}", _0)]
ErrorDeserializingDerivationPath(String),
PrivKeyPolicyNotAllowed(PrivKeyPolicyNotAllowed),
InternalError(String),
}

Expand Down Expand Up @@ -141,8 +147,8 @@ pub async fn eth_coin_from_conf_and_request_v2(
ticker: &str,
conf: &Json,
req: EthActivationV2Request,
priv_key: &[u8],
) -> Result<EthCoin, MmError<EthActivationV2Error>> {
priv_key_policy: PrivKeyBuildPolicy,
) -> MmResult<EthCoin, EthActivationV2Error> {
if req.nodes.is_empty() {
return Err(EthActivationV2Error::AtLeastOneNodeRequired.into());
}
Expand Down Expand Up @@ -182,8 +188,7 @@ pub async fn eth_coin_from_conf_and_request_v2(
}
}

let key_pair: KeyPair =
KeyPair::from_secret_slice(priv_key).map_err(|e| EthActivationV2Error::InternalError(e.to_string()))?;
let key_pair = key_pair_from_priv_key_policy(conf, priv_key_policy)?;
let my_address = checksum_address(&format!("{:02x}", key_pair.address()));

let mut web3_instances = vec![];
Expand Down Expand Up @@ -272,3 +277,29 @@ pub async fn eth_coin_from_conf_and_request_v2(

Ok(EthCoin(Arc::new(coin)))
}

/// Processes the given `priv_key_policy` and generates corresponding `KeyPair`.
/// This function expects either [`PrivKeyBuildPolicy::IguanaPrivKey`]
/// or [`PrivKeyBuildPolicy::GlobalHDAccount`], otherwise returns `PrivKeyPolicyNotAllowed` error.
pub(crate) fn key_pair_from_priv_key_policy(
conf: &Json,
priv_key_policy: PrivKeyBuildPolicy,
) -> MmResult<KeyPair, EthActivationV2Error> {
let priv_key = match priv_key_policy {
artemii235 marked this conversation as resolved.
Show resolved Hide resolved
PrivKeyBuildPolicy::IguanaPrivKey(iguana) => iguana,
PrivKeyBuildPolicy::GlobalHDAccount(global_hd_ctx) => {
// Consider storing `derivation_path` at `EthCoinImpl`.
let derivation_path: Option<StandardHDPathToCoin> = json::from_value(conf["derivation_path"].clone())
.map_to_mm(|e| EthActivationV2Error::ErrorDeserializingDerivationPath(e.to_string()))?;
let derivation_path = derivation_path.or_mm_err(|| EthActivationV2Error::DerivationPathIsNotSet)?;
global_hd_ctx
.derive_secp256k1_secret(&derivation_path)
.mm_err(|e| EthActivationV2Error::InternalError(e.to_string()))?
},
PrivKeyBuildPolicy::Trezor => {
let priv_key_err = PrivKeyPolicyNotAllowed::HardwareWalletNotSupported;
return MmError::err(EthActivationV2Error::PrivKeyPolicyNotAllowed(priv_key_err));
},
};
KeyPair::from_secret_slice(priv_key.as_slice()).map_to_mm(|e| EthActivationV2Error::InternalError(e.to_string()))
}
6 changes: 3 additions & 3 deletions mm2src/coins/hd_pubkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crypto::hw_rpc_task::{HwConnectStatuses, TrezorRpcTaskConnectProcessor};
use crypto::trezor::trezor_rpc_task::{TrezorRpcTaskProcessor, TryIntoUserAction};
use crypto::trezor::utxo::IGNORE_XPUB_MAGIC;
use crypto::trezor::{ProcessTrezorResponse, TrezorError, TrezorProcessingError};
use crypto::{CryptoCtx, CryptoInitError, DerivationPath, EcdsaCurve, HardwareWalletArc, HwError, HwProcessingError,
use crypto::{CryptoCtx, CryptoCtxError, DerivationPath, EcdsaCurve, HardwareWalletArc, HwError, HwProcessingError,
XPub, XPubConverter, XpubError};
use mm2_core::mm_ctx::MmArc;
use mm2_err_handle::prelude::*;
Expand All @@ -22,8 +22,8 @@ pub enum HDExtractPubkeyError {
Internal(String),
}

impl From<CryptoInitError> for HDExtractPubkeyError {
fn from(e: CryptoInitError) -> Self { HDExtractPubkeyError::Internal(e.to_string()) }
impl From<CryptoCtxError> for HDExtractPubkeyError {
fn from(e: CryptoCtxError) -> Self { HDExtractPubkeyError::Internal(e.to_string()) }
}

impl From<TrezorError> for HDExtractPubkeyError {
Expand Down
12 changes: 7 additions & 5 deletions mm2src/coins/hd_wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::hd_pubkey::HDXPubExtractor;
use crate::hd_wallet_storage::HDWalletStorageError;
use crate::{BalanceError, WithdrawError};
use async_trait::async_trait;
use crypto::{Bip32DerPathError, Bip32Error, Bip44Chain, Bip44DerPathError, Bip44DerivationPath, ChildNumber,
DerivationPath, HwError};
use crypto::{Bip32DerPathError, Bip32Error, Bip44Chain, ChildNumber, DerivationPath, HwError, StandardHDPath,
StandardHDPathError};
use derive_more::Display;
use itertools::Itertools;
use mm2_err_handle::prelude::*;
Expand Down Expand Up @@ -125,7 +125,9 @@ pub enum NewAccountCreatingError {
}

impl From<Bip32DerPathError> for NewAccountCreatingError {
fn from(e: Bip32DerPathError) -> Self { NewAccountCreatingError::Internal(Bip44DerPathError::from(e).to_string()) }
fn from(e: Bip32DerPathError) -> Self {
NewAccountCreatingError::Internal(StandardHDPathError::from(e).to_string())
}
}

impl From<HDWalletStorageError> for NewAccountCreatingError {
Expand Down Expand Up @@ -190,8 +192,8 @@ pub struct HDAccountAddressId {
pub address_id: u32,
}

impl From<Bip44DerivationPath> for HDAccountAddressId {
fn from(der_path: Bip44DerivationPath) -> Self {
impl From<StandardHDPath> for HDAccountAddressId {
fn from(der_path: StandardHDPath) -> Self {
HDAccountAddressId {
account_id: der_path.account_id(),
chain: der_path.chain(),
Expand Down
8 changes: 4 additions & 4 deletions mm2src/coins/hd_wallet_storage/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::hd_wallet::HDWalletCoinOps;
use async_trait::async_trait;
use crypto::{CryptoCtx, CryptoInitError, XPub};
use crypto::{CryptoCtx, CryptoCtxError, XPub};
use derive_more::Display;
use mm2_core::mm_ctx::MmArc;
use mm2_err_handle::prelude::*;
Expand Down Expand Up @@ -49,8 +49,8 @@ pub enum HDWalletStorageError {
Internal(String),
}

impl From<CryptoInitError> for HDWalletStorageError {
fn from(e: CryptoInitError) -> Self { HDWalletStorageError::Internal(e.to_string()) }
impl From<CryptoCtxError> for HDWalletStorageError {
fn from(e: CryptoCtxError) -> Self { HDWalletStorageError::Internal(e.to_string()) }
}

impl HDWalletStorageError {
Expand Down Expand Up @@ -226,7 +226,7 @@ impl HDWalletCoinStorage {
let inner = Box::new(HDWalletStorageInstance::init(ctx).await?);
let crypto_ctx = CryptoCtx::from_ctx(ctx)?;
let hd_wallet_rmd160 = crypto_ctx
.hd_wallet_rmd160()
.hw_wallet_rmd160()
.or_mm_err(|| HDWalletStorageError::HDWalletUnavailable)?;
Ok(HDWalletCoinStorage {
coin,
Expand Down
13 changes: 11 additions & 2 deletions mm2src/coins/lightning/ln_errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::utxo::rpc_clients::UtxoRpcError;
use crate::PrivKeyPolicyNotAllowed;
use common::executor::AbortedError;
use common::HttpStatusCode;
use db_common::sqlite::rusqlite::Error as SqlError;
Expand All @@ -11,7 +12,7 @@ use std::num::TryFromIntError;
pub type EnableLightningResult<T> = Result<T, MmError<EnableLightningError>>;
pub type SaveChannelClosingResult<T> = Result<T, MmError<SaveChannelClosingError>>;

#[derive(Clone, Debug, Deserialize, Display, Serialize, SerializeErrorType)]
#[derive(Clone, Debug, Display, Serialize, SerializeErrorType)]
#[serde(tag = "error_type", content = "error_data")]
pub enum EnableLightningError {
#[display(fmt = "Invalid request: {}", _0)]
Expand All @@ -26,6 +27,8 @@ pub enum EnableLightningError {
InvalidAddress(String),
#[display(fmt = "Invalid path: {}", _0)]
InvalidPath(String),
#[display(fmt = "Private key policy is not allowed: {}", _0)]
PrivKeyPolicyNotAllowed(PrivKeyPolicyNotAllowed),
#[display(fmt = "System time error {}", _0)]
SystemTimeError(String),
#[display(fmt = "RPC error {}", _0)]
Expand All @@ -42,7 +45,9 @@ pub enum EnableLightningError {
impl HttpStatusCode for EnableLightningError {
fn status_code(&self) -> StatusCode {
match self {
EnableLightningError::InvalidRequest(_) | EnableLightningError::RpcError(_) => StatusCode::BAD_REQUEST,
EnableLightningError::InvalidRequest(_)
| EnableLightningError::RpcError(_)
| EnableLightningError::PrivKeyPolicyNotAllowed(_) => StatusCode::BAD_REQUEST,
EnableLightningError::UnsupportedMode(_, _) => StatusCode::NOT_IMPLEMENTED,
EnableLightningError::InvalidAddress(_)
| EnableLightningError::InvalidPath(_)
Expand All @@ -69,6 +74,10 @@ impl From<UtxoRpcError> for EnableLightningError {
fn from(e: UtxoRpcError) -> Self { EnableLightningError::RpcError(e.to_string()) }
}

impl From<PrivKeyPolicyNotAllowed> for EnableLightningError {
fn from(e: PrivKeyPolicyNotAllowed) -> Self { EnableLightningError::PrivKeyPolicyNotAllowed(e) }
}

impl From<RpcTaskError> for EnableLightningError {
fn from(e: RpcTaskError) -> Self { EnableLightningError::RpcTaskError(e.to_string()) }
}
Expand Down
4 changes: 2 additions & 2 deletions mm2src/coins/lightning/ln_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ fn sign_funding_transaction(
let my_address = coin
.as_ref()
.derivation_method
.iguana_or_err()
.single_addr_or_err()
.map_err(|e| SignFundingTransactionError::Internal(e.to_string()))?;
let key_pair = coin
.as_ref()
Expand Down Expand Up @@ -526,7 +526,7 @@ impl LightningEventHandler {
}

// Todo: add support for Hardware wallets for funding transactions and spending spendable outputs (channel closing transactions)
let my_address = match self.platform.coin.as_ref().derivation_method.iguana_or_err() {
let my_address = match self.platform.coin.as_ref().derivation_method.single_addr_or_err() {
Ok(addr) => addr.clone(),
Err(e) => {
error!("{}", e);
Expand Down
12 changes: 10 additions & 2 deletions mm2src/coins/lightning/ln_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,17 @@ pub async fn init_db(ctx: &MmArc, ticker: String) -> EnableLightningResult<Sqlit
Ok(db)
}

pub fn init_keys_manager(ctx: &MmArc) -> EnableLightningResult<Arc<KeysManager>> {
pub fn init_keys_manager(platform: &Platform) -> EnableLightningResult<Arc<KeysManager>> {
// The current time is used to derive random numbers from the seed where required, to ensure all random generation is unique across restarts.
let seed: [u8; 32] = ctx.secp256k1_key_pair().private().secret.into();
// TODO validate that this is right
let seed: [u8; 32] = platform
.coin
.as_ref()
.priv_key_policy
.key_pair_or_err()?
.private()
.secret
.into();
Comment on lines +82 to +92
Copy link
Author

Choose a reason for hiding this comment

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

@shamardy could you please confirm that we can use the platform's key-pair to initialize the KeysManager?

Copy link
Collaborator

Choose a reason for hiding this comment

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

My understanding is that if mm2 is started with a global hd account the key pair here will be the one corresponding to a valid child address so I don't think this will be a problem. Now, this private key will be used as seed in KeysManager to generate a new master key that should generate other multiple child keys (a total of six) for node public/private key, closing channels address, and some of these child keys (e.g. channel_master_key) are used as master keys again :) You can check the KeysManager::new function internals for the exact details https://github.com/KomodoPlatform/atomicDEX-API/blob/5627cded1616e34c67b795023514a2a86b4c3bba/mm2src/coins/lightning/ln_utils.rs#L95
We have two choices here, either have one lightning node per user that uses the below master seed https://github.com/KomodoPlatform/atomicDEX-API/blob/5627cded1616e34c67b795023514a2a86b4c3bba/mm2src/crypto/src/privkey.rs#L121-L122 as it's KeysManager seed, or to give the user the ability to have a lightning wallet/node for every child address using the current implementation in this PR. I think we would need @artemii235 input on which of these options is prefered.

Copy link
Member

Choose a reason for hiding this comment

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

@shamardy Will this effect from which address the funding transaction will be sent and to which address closed channel funds will be claimed?

Copy link
Collaborator

@shamardy shamardy Nov 4, 2022

Choose a reason for hiding this comment

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

You are right. For every key pair there will be a different funding/claiming address (funding and claiming addresses are one and the same address of the platform coin), but currently lightning can't be enabled in HDWallet mode, I even added a todo for this in the past, I thought then that HDWallet meant hardware :) https://github.com/KomodoPlatform/atomicDEX-API/blob/5627cded1616e34c67b795023514a2a86b4c3bba/mm2src/coins/lightning.rs#L1178-L1184
https://github.com/KomodoPlatform/atomicDEX-API/blob/5627cded1616e34c67b795023514a2a86b4c3bba/mm2src/coins/lightning/ln_events.rs#L528-L535
https://github.com/KomodoPlatform/atomicDEX-API/blob/5627cded1616e34c67b795023514a2a86b4c3bba/mm2src/coins/rpc_command/lightning/open_channel.rs#L148
If we agreed to have a lightning address/node for every child address, I should add HDWallet implementation for lightning to this checklist #1045 (comment)

Copy link
Collaborator

Choose a reason for hiding this comment

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

One more note, we can always implement our own lightning KeysManager if we needed that. The only requirement for KeysManager is to implement the KeysInterface trait. But I think the one implemented in rust-lightning is very good for preserving privacy, we break this privacy in our lightning implementation when claiming the closing funds back to the same address the channel was opened from. I guess to continue the preserving of privacy with HDWallets we can let the user decide which child address to generate funding from and which address to claim the closing funds to for every channel, if we choose to use only one lightning node for all platform coin addresses then we would need to implement our own lightning KeysManager where there is one node address using the master seed and change the destination script, the shutdown pubkey when switching addresses.

Copy link
Author

Choose a reason for hiding this comment

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

HDWallet is related to Hardware wallet only.
Global HD account is implemented the way that if the user wants to switch its Global HD account, he needs to restart mm2 instance with another conf.hd_account_id index.
So for a running mm2 instance with an conf.hd_account_id value there is only one address (therefore one key-pair) for any coin.

Copy link
Collaborator

Choose a reason for hiding this comment

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

mmm, I understand now but I think we should change DerivationMethod::HDWallet naming to convey that it's for hardware wallets only to avoid confusion.
So, in light of this info, for every conf.hd_account_id there will be a different lightning address/node with different channels backups etc..., I still see no problem caused in lightning by the current implementation :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

For the privacy issues I detailed here #1512 (comment), there will be a different destination script and shutdown pubkey also for every hd_account_id, I guess we can add an option for the user to claim the closing transaction of a channel to a different hd_account_id or a different address of his choosing making lightning channels opening/closing completely private. Of Course this is not a priority now, but just adding my thoughts about HD accounts implications for lightning.

Copy link
Author

Choose a reason for hiding this comment

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

Ok thank you! DerivationMethod::HDWallet is really a confusing name, because it overlaps with Global HD account. But they are both related to HD wallet:

  1. Global HD account: one coin -> one address.
  2. DerivationMethod::HDWallet: one coin -> multiple accounts, account -> multiple addresses (internals and/or externals).

I explained it in more details here: https://github.com/KomodoPlatform/air_dex/issues/502#issuecomment-1193167304

DerivationMethod::HDWallet is currently used with Trezor only, but it's designed the way that it's independent from the private key policy. Thus later we can add new PrivKeyPolicy::CoinHDAccount, for example. The only difference from PrivKeyPolicy::CoinHDAccount will be how transactions are signed.

If we're sure that we don't plan to support such derivation in the future, I can rename DerivationMethod::HDWallet to DerivationMethod::HardwareWallet.
@artemii235 could you please advice?

Copy link
Member

Choose a reason for hiding this comment

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

If we're sure that we don't plan to support such derivation in the future

We can't 100% sure, I guess 🙂 Though, I would prefer the naming to reflect the current meaning of the code. We can figure out one more renaming later if required.

let cur = get_local_duration_since_epoch().map_to_mm(|e| EnableLightningError::SystemTimeError(e.to_string()))?;

Ok(Arc::new(KeysManager::new(&seed, cur.as_secs(), cur.subsec_nanos())))
Expand Down
Loading