Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c5ccb30
refactor sign_message and enable sign message for specific address fo…
borngraced Apr 29, 2025
7c61845
implement support for utxo
borngraced Apr 29, 2025
529f2a6
add unit test for eth
borngraced Apr 30, 2025
8a42b0e
minor changes to eth test
borngraced Apr 30, 2025
b23b8fc
implement utxo unit test
borngraced Apr 30, 2025
d323812
apply onur's patch
borngraced Apr 30, 2025
ad7e0b5
fix review notes and validate coin type
borngraced May 1, 2025
032faff
Merge branch 'dev' into hd-multi-addr-msg-sign
borngraced May 1, 2025
6d4332e
impl Display for Bip32Deri..
borngraced May 1, 2025
9e9081e
nits
borngraced May 2, 2025
187284d
validate comps that makes up path_to_coin
borngraced May 3, 2025
b10fd57
impl path_to_coin method and use for rpc derivation_path validation
borngraced May 5, 2025
5fcef99
Merge branch 'dev' into hd-multi-addr-msg-sign
borngraced May 7, 2025
791c64b
rename WithdrawFrom and reuse in SignatureRequest -< message signing
borngraced May 8, 2025
8489bb0
fmt
borngraced May 8, 2025
67266b1
rename HdAccountIdentifier to AddressIdentifier
borngraced May 8, 2025
ca176d8
fmt
borngraced May 8, 2025
38eb5dd
Merge branch 'dev' into hd-multi-addr-msg-sign
borngraced May 20, 2025
b453126
fix review notes
borngraced May 22, 2025
e7add30
Merge branch 'dev' into hd-multi-addr-msg-sign
borngraced May 22, 2025
ecc6eb7
post merge fix
borngraced May 22, 2025
98a5b6c
Merge branch 'dev' into hd-multi-addr-msg-sign
borngraced May 26, 2025
df2bbed
rename AddressIdentifier to HDAddressSelector and update doc comments
borngraced May 27, 2025
935409d
apply segwit sign-verify patch by Omar
borngraced May 27, 2025
9f0bde4
cargo fmt
borngraced May 27, 2025
8180da3
impl unit test for address conflict caused by derivation_paths
borngraced May 27, 2025
4d91373
clippy
borngraced May 27, 2025
860c208
fix naming and minor changes
borngraced May 28, 2025
3ade61b
update lp_coins sign_message
borngraced May 28, 2025
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
36 changes: 32 additions & 4 deletions mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ use common::log::{debug, error, info, warn};
use common::number_type_casting::SafeTypeCastingNumbers;
use common::{now_sec, small_rng, DEX_FEE_ADDR_RAW_PUBKEY};
use crypto::privkey::key_pair_from_secret;
use crypto::{Bip44Chain, CryptoCtx, CryptoCtxError, GlobalHDAccountArc, KeyPairPolicy};
use crypto::{Bip44Chain, CryptoCtx, CryptoCtxError, GlobalHDAccountArc, KeyPairPolicy, StandardHDPath};
use derive_more::Display;
use enum_derives::EnumFromStringify;

Expand Down Expand Up @@ -2328,10 +2328,38 @@ impl MarketCoinOps for EthCoin {
Some(keccak256(&stream.out()).take())
}

fn sign_message(&self, message: &str) -> SignatureResult<String> {
fn sign_message(&self, message: &str, derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
let message_hash = self.sign_message_hash(message).ok_or(SignatureError::PrefixNotFound)?;
let privkey = &self.priv_key_policy.activated_key_or_err()?.secret();
let signature = sign(privkey, &H256::from(message_hash))?;

let signature = match derivation_path {
Some(derivation_path) => {
let expected_path_to_coin = self.priv_key_policy.path_to_coin_or_err()?;
let rpc_path = StandardHDPath::try_from(derivation_path.clone())?;
let path_to_coin = rpc_path.path_to_coin();

if expected_path_to_coin != &path_to_coin {
let error = format!(
"Derivation path '{:?}' must have '{:?}' coin path",
derivation_path, expected_path_to_coin
);
return MmError::err(SignatureError::InvalidRequest(error));
};

let privkey = self
.priv_key_policy
.hd_wallet_derived_priv_key_or_err(&derivation_path)?;
let secret = ethkey::Secret::from_slice(privkey.as_slice()).ok_or(MmError::new(
SignatureError::InternalError("failed to derive ethkey::Secret".to_string()),
))?;

sign(&secret, &H256::from(message_hash))?
},
None => {
let secret = self.priv_key_policy.activated_key_or_err()?.secret();
sign(secret, &H256::from(message_hash))?
},
};

Ok(format!("0x{}", signature))
}

Expand Down
2 changes: 1 addition & 1 deletion mm2src/coins/eth/eth_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ fn test_sign_verify_message() {
);

let message = "test";
let signature = coin.sign_message(message).unwrap();
let signature = coin.sign_message(message, None).unwrap();
assert_eq!(signature, "0xcdf11a9c4591fb7334daa4b21494a2590d3f7de41c7d2b333a5b61ca59da9b311b492374cc0ba4fbae53933260fa4b1c18f15d95b694629a7b0620eec77a938600");

let is_valid = coin
Expand Down
8 changes: 7 additions & 1 deletion mm2src/coins/lightning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::{BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, ConfirmPaymentInp
ValidatePaymentInput, VerificationError, VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps,
WeakSpawner, WithdrawError, WithdrawFut, WithdrawRequest};
use async_trait::async_trait;
use bip32::DerivationPath;
use bitcoin::bech32::ToBase32;
use bitcoin::hashes::Hash;
use bitcoin_hashes::sha256::Hash as Sha256;
Expand Down Expand Up @@ -950,7 +951,12 @@ impl MarketCoinOps for LightningCoin {
Some(dhash256(prefixed_message.as_bytes()).take())
}

fn sign_message(&self, message: &str) -> SignatureResult<String> {
fn sign_message(&self, message: &str, derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
if derivation_path.is_some() {
return MmError::err(SignatureError::InvalidRequest(
"functionality not supported for Lightning yet.".into(),
));
}
let message_hash = self.sign_message_hash(message).ok_or(SignatureError::PrefixNotFound)?;
let secret_key = self
.keys_manager
Expand Down
16 changes: 12 additions & 4 deletions mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ use common::custom_futures::timeout::TimeoutError;
use common::executor::{abortable_queue::WeakSpawner, AbortedError, SpawnFuture};
use common::log::{warn, LogOnError};
use common::{calc_total_pages, now_sec, ten, HttpStatusCode, DEX_BURN_ADDR_RAW_PUBKEY, DEX_FEE_ADDR_RAW_PUBKEY};
use crypto::{derive_secp256k1_secret, Bip32Error, Bip44Chain, CryptoCtx, CryptoCtxError, DerivationPath,
GlobalHDAccountArc, HDPathToCoin, HwRpcError, KeyPairPolicy, RpcDerivationPath,
use crypto::{derive_secp256k1_secret, Bip32DerPathError, Bip32Error, Bip44Chain, CryptoCtx, CryptoCtxError,
DerivationPath, GlobalHDAccountArc, HDPathToCoin, HwRpcError, KeyPairPolicy, RpcDerivationPath,
Secp256k1ExtendedPublicKey, Secp256k1Secret, WithHwRpcError};
use derive_more::Display;
use enum_derives::{EnumFromStringify, EnumFromTrait};
Expand Down Expand Up @@ -2084,7 +2084,7 @@ pub trait MarketCoinOps {

fn sign_message_hash(&self, _message: &str) -> Option<[u8; 32]>;

fn sign_message(&self, _message: &str) -> SignatureResult<String>;
fn sign_message(&self, _message: &str, _derivation_path: Option<DerivationPath>) -> SignatureResult<String>;

fn verify_message(&self, _signature: &str, _message: &str, _address: &str) -> VerificationResult<bool>;

Expand Down Expand Up @@ -2299,6 +2299,7 @@ pub enum ValidatorsInfoDetails {
pub struct SignatureRequest {
coin: String,
message: String,
derivation_path: Option<RpcDerivationPath>,
Comment thread
shamardy marked this conversation as resolved.
Outdated
}

#[derive(Serialize, Deserialize)]
Expand Down Expand Up @@ -3358,6 +3359,7 @@ impl WithdrawError {
#[derive(Debug, Display, EnumFromStringify, Serialize, SerializeErrorType)]
#[serde(tag = "error_type", content = "error_data")]
pub enum SignatureError {
#[from_stringify("Bip32DerPathError")]
Comment thread
shamardy marked this conversation as resolved.
Outdated
#[display(fmt = "Invalid request: {}", _0)]
InvalidRequest(String),
#[from_stringify("CoinFindError", "ethkey::Error", "keys::Error", "PrivKeyPolicyNotAllowed")]
Expand Down Expand Up @@ -5112,8 +5114,14 @@ pub async fn get_raw_transaction(ctx: MmArc, req: RawTransactionRequest) -> RawT
}

pub async fn sign_message(ctx: MmArc, req: SignatureRequest) -> SignatureResult<SignatureResponse> {
if req.derivation_path.is_some() && !ctx.enable_hd() {
return MmError::err(SignatureError::InvalidRequest(
"You need to enable kdf with enable_hd to use derivation_path".to_string(),
));
};
let coin = lp_coinfind_or_err(&ctx, &req.coin).await?;
let signature = coin.sign_message(&req.message)?;
let signature = coin.sign_message(&req.message, req.derivation_path.map(|d| d.0))?;

Ok(SignatureResponse { signature })
}

Expand Down
5 changes: 3 additions & 2 deletions mm2src/coins/qrc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, Con
ValidatePaymentInput, VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps, WeakSpawner, WithdrawError,
WithdrawFee, WithdrawFut, WithdrawRequest, WithdrawResult};
use async_trait::async_trait;
use bip32::DerivationPath;
use bitcrypto::{dhash160, sha256};
use chain::TransactionOutput;
use common::executor::{AbortableSystem, AbortedError, Timer};
Expand Down Expand Up @@ -1039,8 +1040,8 @@ impl MarketCoinOps for Qrc20Coin {
utxo_common::sign_message_hash(self.as_ref(), message)
}

fn sign_message(&self, message: &str) -> SignatureResult<String> {
utxo_common::sign_message(self.as_ref(), message)
fn sign_message(&self, message: &str, derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
utxo_common::sign_message(self.as_ref(), message, derivation_path)
}

fn verify_message(&self, signature_base64: &str, message: &str, address: &str) -> VerificationResult<bool> {
Expand Down
14 changes: 10 additions & 4 deletions mm2src/coins/siacoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use crate::{coin_errors::MyAddressError, BalanceFut, CanRefundHtlc, CheckIfMyPay
TradePreimageValue, TransactionResult, TxMarshalingErr, UnexpectedDerivationMethod, ValidateAddressResult,
ValidateFeeArgs, ValidateOtherPubKeyErr, ValidatePaymentInput, ValidatePaymentResult, VerificationResult,
WaitForHTLCTxSpendArgs, WatcherOps, WeakSpawner, WithdrawFut, WithdrawRequest};
use crate::{SignatureError, VerificationError};
use async_trait::async_trait;
use bip32::DerivationPath;
use common::executor::AbortedError;
pub use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature};
use futures::{FutureExt, TryFutureExt};
Expand Down Expand Up @@ -312,14 +314,18 @@ impl MarketCoinOps for SiaCoin {
Ok(address.to_string())
}

async fn get_public_key(&self) -> Result<String, MmError<UnexpectedDerivationMethod>> { unimplemented!() }
async fn get_public_key(&self) -> Result<String, MmError<UnexpectedDerivationMethod>> {
MmError::err(UnexpectedDerivationMethod::InternalError("Not implemented".into()))
}

fn sign_message_hash(&self, _message: &str) -> Option<[u8; 32]> { unimplemented!() }
fn sign_message_hash(&self, _message: &str) -> Option<[u8; 32]> { None }

fn sign_message(&self, _message: &str) -> SignatureResult<String> { unimplemented!() }
fn sign_message(&self, _message: &str, _derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
MmError::err(SignatureError::InternalError("Not implemented".into()))
}

fn verify_message(&self, _signature: &str, _message: &str, _address: &str) -> VerificationResult<bool> {
unimplemented!()
MmError::err(VerificationError::InternalError("Not implemented".into()))
Comment on lines +330 to +337

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 guess we will need those once SIA implementation is completed. Can you please open an issue for both this and tendermint and any other missing implementation @borngraced

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.

}

fn my_balance(&self) -> BalanceFut<CoinBalance> {
Expand Down
2 changes: 1 addition & 1 deletion mm2src/coins/tendermint/tendermint_coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3334,7 +3334,7 @@ impl MarketCoinOps for TendermintCoin {
None
}

fn sign_message(&self, _message: &str) -> SignatureResult<String> {
fn sign_message(&self, _message: &str, _derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
// TODO
MmError::err(SignatureError::InternalError("Not implemented".into()))
}
Expand Down
5 changes: 4 additions & 1 deletion mm2src/coins/tendermint/tendermint_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::{big_decimal_from_sat_unsigned, utxo::sat_from_big_decimal, BalanceFu
ValidatePaymentInput, VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps, WeakSpawner, WithdrawError,
WithdrawFut, WithdrawRequest};
use async_trait::async_trait;
use bip32::DerivationPath;
use bitcrypto::sha256;
use common::executor::abortable_queue::AbortableQueue;
use common::executor::{AbortableSystem, AbortedError};
Expand Down Expand Up @@ -275,7 +276,9 @@ impl MarketCoinOps for TendermintToken {

fn sign_message_hash(&self, message: &str) -> Option<[u8; 32]> { self.platform_coin.sign_message_hash(message) }

fn sign_message(&self, message: &str) -> SignatureResult<String> { self.platform_coin.sign_message(message) }
fn sign_message(&self, message: &str, derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
self.platform_coin.sign_message(message, derivation_path)
}

fn verify_message(&self, signature: &str, message: &str, address: &str) -> VerificationResult<bool> {
self.platform_coin.verify_message(signature, message, address)
Expand Down
5 changes: 4 additions & 1 deletion mm2src/coins/test_coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::{coin_errors::MyAddressError, BalanceFut, CanRefundHtlc, CheckIfMyPay
WatcherValidatePaymentInput, WatcherValidateTakerFeeInput, WeakSpawner, WithdrawFut, WithdrawRequest};
use crate::{DexFee, ToBytes, ValidateWatcherSpendInput};
use async_trait::async_trait;
use bip32::DerivationPath;
use common::executor::AbortedError;
use futures01::Future;
use keys::KeyPair;
Expand Down Expand Up @@ -69,7 +70,9 @@ impl MarketCoinOps for TestCoin {

fn sign_message_hash(&self, _message: &str) -> Option<[u8; 32]> { unimplemented!() }

fn sign_message(&self, _message: &str) -> SignatureResult<String> { unimplemented!() }
fn sign_message(&self, _message: &str, _derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
unimplemented!()
}

fn verify_message(&self, _signature: &str, _message: &str, _address: &str) -> VerificationResult<bool> {
unimplemented!()
Expand Down
6 changes: 3 additions & 3 deletions mm2src/coins/utxo/bch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1147,8 +1147,8 @@ impl MarketCoinOps for BchCoin {
utxo_common::sign_message_hash(self.as_ref(), message)
}

fn sign_message(&self, message: &str) -> SignatureResult<String> {
utxo_common::sign_message(self.as_ref(), message)
fn sign_message(&self, message: &str, derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
utxo_common::sign_message(self.as_ref(), message, derivation_path)
}

fn verify_message(&self, signature_base64: &str, message: &str, address: &str) -> VerificationResult<bool> {
Expand Down Expand Up @@ -1703,7 +1703,7 @@ mod bch_tests {
#[test]
fn test_sign_message() {
let (_ctx, coin) = tbch_coin_for_test();
let signature = coin.sign_message("test").unwrap();
let signature = coin.sign_message("test", None).unwrap();
assert_eq!(
signature,
"ILuePKMsycXwJiNDOT7Zb7TfIlUW7Iq+5ylKd15AK72vGVYXbnf7Gj9Lk9MFV+6Ub955j7MiAkp0wQjvuIoRPPA="
Expand Down
4 changes: 2 additions & 2 deletions mm2src/coins/utxo/qtum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,8 +770,8 @@ impl MarketCoinOps for QtumCoin {
utxo_common::sign_message_hash(self.as_ref(), message)
}

fn sign_message(&self, message: &str) -> SignatureResult<String> {
utxo_common::sign_message(self.as_ref(), message)
fn sign_message(&self, message: &str, _derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
utxo_common::sign_message(self.as_ref(), message, None)
}

fn verify_message(&self, signature_base64: &str, message: &str, address: &str) -> VerificationResult<bool> {
Expand Down
7 changes: 4 additions & 3 deletions mm2src/coins/utxo/slp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::{BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, ConfirmPaymentInp
use async_trait::async_trait;
use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use bip32::DerivationPath;
use bitcrypto::dhash160;
use chain::constants::SEQUENCE_FINAL;
use chain::{OutPoint, TransactionOutput};
Expand Down Expand Up @@ -1117,8 +1118,8 @@ impl MarketCoinOps for SlpToken {
utxo_common::sign_message_hash(self.as_ref(), message)
}

fn sign_message(&self, message: &str) -> SignatureResult<String> {
utxo_common::sign_message(self.as_ref(), message)
fn sign_message(&self, message: &str, derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
utxo_common::sign_message(self.as_ref(), message, derivation_path)
}

fn verify_message(&self, signature: &str, message: &str, address: &str) -> VerificationResult<bool> {
Expand Down Expand Up @@ -2167,7 +2168,7 @@ mod slp_tests {
let (_ctx, bch) = tbch_coin_for_test();
let token_id = H256::from("bb309e48930671582bea508f9a1d9b491e49b69be3d6f372dc08da2ac6e90eb7");
let fusd = SlpToken::new(4, "FUSD".into(), token_id, bch, 0).unwrap();
let signature = fusd.sign_message("test").unwrap();
let signature = fusd.sign_message("test", None).unwrap();
assert_eq!(
signature,
"ILuePKMsycXwJiNDOT7Zb7TfIlUW7Iq+5ylKd15AK72vGVYXbnf7Gj9Lk9MFV+6Ub955j7MiAkp0wQjvuIoRPPA="
Expand Down
37 changes: 34 additions & 3 deletions mm2src/coins/utxo/utxo_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use chain::{OutPoint, TransactionInput, TransactionOutput};
use common::executor::Timer;
use common::jsonrpc_client::JsonRpcErrorType;
use common::log::{debug, error};
use crypto::Bip44Chain;
use crypto::{Bip44Chain, StandardHDPath};
use futures::compat::Future01CompatExt;
use futures::future::{FutureExt, TryFutureExt};
use futures01::future::Either;
Expand Down Expand Up @@ -2755,9 +2755,40 @@ pub fn sign_message_hash(coin: &UtxoCoinFields, message: &str) -> Option<[u8; 32
Some(dhash256(&stream.out()).take())
}

pub fn sign_message(coin: &UtxoCoinFields, message: &str) -> SignatureResult<String> {
pub fn sign_message(
coin: &UtxoCoinFields,
message: &str,
derivation_path: Option<DerivationPath>,
) -> SignatureResult<String> {
let message_hash = sign_message_hash(coin, message).ok_or(SignatureError::PrefixNotFound)?;
let private_key = coin.priv_key_policy.activated_key_or_err()?.private();
let private_key = match derivation_path {
Some(derivation_path) => {
let expected_path_to_coin = coin.priv_key_policy.path_to_coin_or_err()?;
let rpc_path = StandardHDPath::try_from(derivation_path.clone())?;
let path_to_coin = rpc_path.path_to_coin();

if expected_path_to_coin != &path_to_coin {
let error = format!(
"Derivation path '{:?}' must have '{:?}' coin path",
derivation_path, expected_path_to_coin
);
return MmError::err(SignatureError::InvalidRequest(error));
};

let privkey = coin
.priv_key_policy
.hd_wallet_derived_priv_key_or_err(&derivation_path)?;

Private {
prefix: coin.conf.wif_prefix,
secret: privkey,
compressed: true,
checksum_type: coin.conf.checksum_type,
}
},
None => *coin.priv_key_policy.activated_key_or_err()?.private(),
};

let signature = private_key.sign_compact(&H256::from(message_hash))?;
Ok(STANDARD.encode(&*signature))
}
Expand Down
4 changes: 2 additions & 2 deletions mm2src/coins/utxo/utxo_standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,8 +856,8 @@ impl MarketCoinOps for UtxoStandardCoin {
utxo_common::sign_message_hash(self.as_ref(), message)
}

fn sign_message(&self, message: &str) -> SignatureResult<String> {
utxo_common::sign_message(self.as_ref(), message)
fn sign_message(&self, message: &str, derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
utxo_common::sign_message(self.as_ref(), message, derivation_path)
}

fn verify_message(&self, signature_base64: &str, message: &str, address: &str) -> VerificationResult<bool> {
Expand Down
4 changes: 2 additions & 2 deletions mm2src/coins/utxo/utxo_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4539,7 +4539,7 @@ fn test_sign_verify_message() {
);

let message = "test";
let signature = coin.sign_message(message).unwrap();
let signature = coin.sign_message(message, None).unwrap();
assert_eq!(
signature,
"HzetbqVj9gnUOznon9bvE61qRlmjH5R+rNgkxu8uyce3UBbOu+2aGh7r/GGSVFGZjRnaYC60hdwtdirTKLb7bE4="
Expand All @@ -4560,7 +4560,7 @@ fn test_sign_verify_message_segwit() {
);

let message = "test";
let signature = coin.sign_message(message).unwrap();
let signature = coin.sign_message(message, None).unwrap();
assert_eq!(
signature,
"HzetbqVj9gnUOznon9bvE61qRlmjH5R+rNgkxu8uyce3UBbOu+2aGh7r/GGSVFGZjRnaYC60hdwtdirTKLb7bE4="
Expand Down
3 changes: 2 additions & 1 deletion mm2src/coins/z_coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, Con
WatcherOps, WeakSpawner, WithdrawError, WithdrawFut, WithdrawRequest};

use async_trait::async_trait;
use bip32::DerivationPath;
use bitcrypto::dhash256;
use chain::constants::SEQUENCE_FINAL;
use chain::{Transaction as UtxoTx, TransactionOutput};
Expand Down Expand Up @@ -1143,7 +1144,7 @@ impl MarketCoinOps for ZCoin {

fn sign_message_hash(&self, _message: &str) -> Option<[u8; 32]> { None }

fn sign_message(&self, _message: &str) -> SignatureResult<String> {
fn sign_message(&self, _message: &str, _derivation_path: Option<DerivationPath>) -> SignatureResult<String> {
MmError::err(SignatureError::InvalidRequest(
"Message signing is not supported by the given coin type".to_string(),
))
Expand Down
Loading