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

feat(trading-proto-upgrade): UTXO PoC + State machine refactor #1927

Merged
merged 31 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e4f8e44
WIP. Implementing initial tests.
Jul 11, 2023
0ed2e98
WIP.
Jul 12, 2023
8972b49
WIP. PoC dex fee tests are green.
Jul 12, 2023
b5efde4
WIP. Adding SwapOpsV2. Some refactoring.
artemii235 Jul 14, 2023
3a4b9d0
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
Jul 18, 2023
2102d2f
WIP. Implementing gen_and_sign_dex_fee_spend_preimage.
artemii235 Jul 18, 2023
2bfac14
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Jul 19, 2023
1b62e7f
WIP. Implemented gen_and_sign_dex_fee_spend_preimage.
artemii235 Jul 19, 2023
803bb07
WIP. Implementing validate_dex_fee_spend_preimage.
Jul 19, 2023
0813180
WIP. Implementing sign_and_broadcast_dex_fee_spend.
Jul 20, 2023
762308b
WIP. Debugging sign_and_broadcast_dex_fee_spend.
Jul 20, 2023
95587ab
WIP. swap_proto_v2_tests are green.
Jul 20, 2023
03859b8
Fix clippy.
Jul 21, 2023
88d16a8
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Jul 25, 2023
61a35a0
WIP. Implementing validate_dex_fee_with_premium.
artemii235 Jul 25, 2023
72a9beb
WIP. Finished validate_dex_fee_with_premium for UTXO.
artemii235 Jul 26, 2023
042ee98
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Jul 26, 2023
588f4ba
WIP. Trying to implement StorableStateMachine.
artemii235 Jul 26, 2023
2e78f83
WIP. Trying to refactor state machine.
artemii235 Jul 27, 2023
8dacb49
WIP. Trying to refactor state machine.
artemii235 Jul 28, 2023
0fb998f
Refactored state machine.
Jul 28, 2023
b2c3f56
WIP. Implementing StorableStateMachine.
artemii235 Jul 31, 2023
56c8cb6
WIP. Playing with trait bounds.
artemii235 Aug 1, 2023
925ca00
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Aug 2, 2023
d3af2d5
Fix WASM.
artemii235 Aug 2, 2023
4b7bc7b
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Aug 3, 2023
85f2623
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Aug 4, 2023
ebe7e4f
Fix review notes.
artemii235 Aug 4, 2023
9d99840
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
Aug 9, 2023
95dde3e
Use get instead of direct access by index in validate_dex_fee_spend_p…
Aug 9, 2023
f773d0d
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Aug 15, 2023
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
21 changes: 11 additions & 10 deletions mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ use crate::nft::{find_wallet_nft_amount, WithdrawNftResult};
use v2_activation::{build_address_and_priv_key_policy, EthActivationV2Error};

mod nonce;
use crate::TransactionResult;
use nonce::ParityNonce;

/// https://github.com/artemii235/etomic-swap/blob/master/contracts/EtomicSwap.sol
Expand Down Expand Up @@ -1095,18 +1096,18 @@ impl SwapOps for EthCoin {
)
}

fn send_taker_refunds_payment(&self, taker_refunds_payment_args: RefundPaymentArgs) -> TransactionFut {
Box::new(
self.refund_hash_time_locked_payment(taker_refunds_payment_args)
.map(TransactionEnum::from),
)
async fn send_taker_refunds_payment(&self, taker_refunds_payment_args: RefundPaymentArgs<'_>) -> TransactionResult {
self.refund_hash_time_locked_payment(taker_refunds_payment_args)
.map(TransactionEnum::from)
.compat()
.await
}

fn send_maker_refunds_payment(&self, maker_refunds_payment_args: RefundPaymentArgs) -> TransactionFut {
Box::new(
self.refund_hash_time_locked_payment(maker_refunds_payment_args)
.map(TransactionEnum::from),
)
async fn send_maker_refunds_payment(&self, maker_refunds_payment_args: RefundPaymentArgs<'_>) -> TransactionResult {
self.refund_hash_time_locked_payment(maker_refunds_payment_args)
.map(TransactionEnum::from)
.compat()
.await
}

fn validate_fee(&self, validate_fee_args: ValidateFeeArgs<'_>) -> ValidatePaymentFut<()> {
Expand Down
10 changes: 2 additions & 8 deletions mm2src/coins/eth/eth_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,10 +380,7 @@ fn send_and_refund_erc20_payment() {
swap_unique_data: &[],
watcher_reward: false,
};
let refund = coin
.send_maker_refunds_payment(maker_refunds_payment_args)
.wait()
.unwrap();
let refund = block_on(coin.send_maker_refunds_payment(maker_refunds_payment_args)).unwrap();
log!("{:?}", refund);

let status = block_on(
Expand Down Expand Up @@ -470,10 +467,7 @@ fn send_and_refund_eth_payment() {
swap_unique_data: &[],
watcher_reward: false,
};
let refund = coin
.send_maker_refunds_payment(maker_refunds_payment_args)
.wait()
.unwrap();
let refund = block_on(coin.send_maker_refunds_payment(maker_refunds_payment_args)).unwrap();

log!("{:?}", refund);

Expand Down
26 changes: 16 additions & 10 deletions mm2src/coins/lightning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ use crate::{BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, CoinFutSpawner, C
RefundResult, SearchForSwapTxSpendInput, SendMakerPaymentSpendPreimageInput, SendPaymentArgs,
SignatureError, SignatureResult, SpendPaymentArgs, SwapOps, TakerSwapMakerCoin, TradeFee,
TradePreimageFut, TradePreimageResult, TradePreimageValue, Transaction, TransactionEnum, TransactionErr,
TransactionFut, TxMarshalingErr, UnexpectedDerivationMethod, UtxoStandardCoin, ValidateAddressResult,
ValidateFeeArgs, ValidateInstructionsErr, ValidateOtherPubKeyErr, ValidatePaymentError,
ValidatePaymentFut, ValidatePaymentInput, VerificationError, VerificationResult, WaitForHTLCTxSpendArgs,
WatcherOps, WatcherReward, WatcherRewardError, WatcherSearchForSwapTxSpendInput,
TransactionFut, TransactionResult, TxMarshalingErr, UnexpectedDerivationMethod, UtxoStandardCoin,
ValidateAddressResult, ValidateFeeArgs, ValidateInstructionsErr, ValidateOtherPubKeyErr,
ValidatePaymentError, ValidatePaymentFut, ValidatePaymentInput, VerificationError, VerificationResult,
WaitForHTLCTxSpendArgs, WatcherOps, WatcherReward, WatcherRewardError, WatcherSearchForSwapTxSpendInput,
WatcherValidatePaymentInput, WatcherValidateTakerFeeInput, WithdrawError, WithdrawFut, WithdrawRequest};
use async_trait::async_trait;
use bitcoin::bech32::ToBase32;
Expand Down Expand Up @@ -660,16 +660,22 @@ impl SwapOps for LightningCoin {
self.spend_swap_payment(taker_spends_payment_args)
}

fn send_taker_refunds_payment(&self, _taker_refunds_payment_args: RefundPaymentArgs<'_>) -> TransactionFut {
Box::new(futures01::future::err(TransactionErr::Plain(
async fn send_taker_refunds_payment(
&self,
_taker_refunds_payment_args: RefundPaymentArgs<'_>,
) -> TransactionResult {
Err(TransactionErr::Plain(
"Doesn't need transaction broadcast to refund lightning HTLC".into(),
)))
))
}

fn send_maker_refunds_payment(&self, _maker_refunds_payment_args: RefundPaymentArgs<'_>) -> TransactionFut {
Box::new(futures01::future::err(TransactionErr::Plain(
async fn send_maker_refunds_payment(
&self,
_maker_refunds_payment_args: RefundPaymentArgs<'_>,
) -> TransactionResult {
Err(TransactionErr::Plain(
"Doesn't need transaction broadcast to refund lightning HTLC".into(),
)))
))
}

// Todo: This validates the dummy fee for now for the sake of swap P.O.C., this should be implemented probably after agreeing on how fees will work for lightning
Expand Down
135 changes: 133 additions & 2 deletions mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ pub mod z_coin;
use z_coin::{ZCoin, ZcoinProtocolInfo};

pub type TransactionFut = Box<dyn Future<Item = TransactionEnum, Error = TransactionErr> + Send>;
pub type TransactionResult = Result<TransactionEnum, TransactionErr>;
pub type BalanceResult<T> = Result<T, MmError<BalanceError>>;
pub type BalanceFut<T> = Box<dyn Future<Item = T, Error = MmError<BalanceError>> + Send>;
pub type NonZeroBalanceFut<T> = Box<dyn Future<Item = T, Error = MmError<GetNonZeroBalance>> + Send>;
Expand All @@ -310,6 +311,9 @@ pub type RawTransactionResult = Result<RawTransactionRes, MmError<RawTransaction
pub type RawTransactionFut<'a> =
Box<dyn Future<Item = RawTransactionRes, Error = MmError<RawTransactionError>> + Send + 'a>;
pub type RefundResult<T> = Result<T, MmError<RefundError>>;
pub type GenAndSignDexFeeSpendResult = MmResult<TxPreimageWithSig, TxGenError>;
pub type ValidateDexFeeResult = MmResult<(), ValidateDexFeeError>;
pub type ValidateDexFeeSpendPreimageResult = MmResult<(), ValidateDexFeeSpendPreimageError>;

pub type IguanaPrivKey = Secp256k1Secret;

Expand Down Expand Up @@ -821,9 +825,9 @@ pub trait SwapOps {

fn send_taker_spends_maker_payment(&self, taker_spends_payment_args: SpendPaymentArgs<'_>) -> TransactionFut;

fn send_taker_refunds_payment(&self, taker_refunds_payment_args: RefundPaymentArgs<'_>) -> TransactionFut;
async fn send_taker_refunds_payment(&self, taker_refunds_payment_args: RefundPaymentArgs<'_>) -> TransactionResult;

fn send_maker_refunds_payment(&self, maker_refunds_payment_args: RefundPaymentArgs<'_>) -> TransactionFut;
async fn send_maker_refunds_payment(&self, maker_refunds_payment_args: RefundPaymentArgs<'_>) -> TransactionResult;

fn validate_fee(&self, validate_fee_args: ValidateFeeArgs<'_>) -> ValidatePaymentFut<()>;

Expand Down Expand Up @@ -989,6 +993,133 @@ pub trait WatcherOps {
) -> Result<Option<WatcherReward>, MmError<WatcherRewardError>>;
}

pub struct SendDexFeeWithPremiumArgs<'a> {
pub time_lock: u32,
pub secret_hash: &'a [u8],
pub other_pub: &'a [u8],
pub dex_fee_amount: BigDecimal,
pub premium_amount: BigDecimal,
pub swap_unique_data: &'a [u8],
}

pub struct ValidateDexFeeArgs<'a> {
pub dex_fee_tx: &'a [u8],
pub time_lock: u32,
pub secret_hash: &'a [u8],
pub other_pub: &'a [u8],
pub dex_fee_amount: BigDecimal,
pub premium_amount: BigDecimal,
pub swap_unique_data: &'a [u8],
}

pub struct GenDexFeeSpendArgs<'a> {
pub dex_fee_tx: &'a [u8],
pub time_lock: u32,
pub secret_hash: &'a [u8],
pub maker_pub: &'a [u8],
pub taker_pub: &'a [u8],
pub dex_fee_pub: &'a [u8],
pub dex_fee_amount: BigDecimal,
pub premium_amount: BigDecimal,
}

pub struct TxPreimageWithSig {
preimage: Vec<u8>,
signature: Vec<u8>,
}

#[derive(Debug)]
pub enum TxGenError {
Rpc(String),
NumConversion(String),
AddressDerivation(String),
TxDeserialization(String),
InvalidPubkey(String),
Signing(String),
MinerFeeExceedsPremium { miner_fee: BigDecimal, premium: BigDecimal },
Legacy(String),
}

impl From<UtxoRpcError> for TxGenError {
fn from(err: UtxoRpcError) -> Self { TxGenError::Rpc(err.to_string()) }
}

impl From<NumConversError> for TxGenError {
fn from(err: NumConversError) -> Self { TxGenError::NumConversion(err.to_string()) }
}

impl From<UtxoSignWithKeyPairError> for TxGenError {
fn from(err: UtxoSignWithKeyPairError) -> Self { TxGenError::Signing(err.to_string()) }
}

#[derive(Debug)]
pub enum ValidateDexFeeError {
InvalidDestinationOrAmount(String),
InvalidPubkey(String),
NumConversion(String),
Rpc(String),
TxBytesMismatch { from_rpc: BytesJson, actual: BytesJson },
TxDeserialization(String),
TxLacksOfOutputs,
}

impl From<NumConversError> for ValidateDexFeeError {
fn from(err: NumConversError) -> Self { ValidateDexFeeError::NumConversion(err.to_string()) }
}

impl From<UtxoRpcError> for ValidateDexFeeError {
fn from(err: UtxoRpcError) -> Self { ValidateDexFeeError::Rpc(err.to_string()) }
}

#[derive(Debug)]
pub enum ValidateDexFeeSpendPreimageError {
InvalidPubkey(String),
InvalidTakerSignature,
InvalidPreimage(String),
SignatureVerificationFailure(String),
TxDeserialization(String),
TxGenError(String),
}

impl From<UtxoSignWithKeyPairError> for ValidateDexFeeSpendPreimageError {
fn from(err: UtxoSignWithKeyPairError) -> Self {
ValidateDexFeeSpendPreimageError::SignatureVerificationFailure(err.to_string())
}
}

impl From<TxGenError> for ValidateDexFeeSpendPreimageError {
fn from(err: TxGenError) -> Self { ValidateDexFeeSpendPreimageError::TxGenError(format!("{:?}", err)) }
}

#[async_trait]
pub trait SwapOpsV2 {
async fn send_dex_fee_with_premium(&self, args: SendDexFeeWithPremiumArgs<'_>) -> TransactionResult;

async fn validate_dex_fee_with_premium(&self, args: ValidateDexFeeArgs<'_>) -> ValidateDexFeeResult;

async fn refund_dex_fee_with_premium(&self, args: RefundPaymentArgs<'_>) -> TransactionResult;

async fn gen_and_sign_dex_fee_spend_preimage(
&self,
args: &GenDexFeeSpendArgs<'_>,
swap_unique_data: &[u8],
) -> GenAndSignDexFeeSpendResult;

async fn validate_dex_fee_spend_preimage(
&self,
gen_args: &GenDexFeeSpendArgs<'_>,
preimage: &TxPreimageWithSig,
) -> ValidateDexFeeSpendPreimageResult;

async fn sign_and_broadcast_dex_fee_spend(
&self,
preimage: &TxPreimageWithSig,
gen_args: &GenDexFeeSpendArgs<'_>,
secret: &[u8],
swap_unique_data: &[u8],
) -> TransactionResult;
}

/// Operations that coins have independently from the MarketMaker.
/// That is, things implemented by the coin wallets or public coin services.
pub trait MarketCoinOps {
Expand Down
42 changes: 16 additions & 26 deletions mm2src/coins/qrc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinBalance, Coi
RawTransactionRequest, RefundError, RefundPaymentArgs, RefundResult, SearchForSwapTxSpendInput,
SendMakerPaymentSpendPreimageInput, SendPaymentArgs, SignatureResult, SpendPaymentArgs, SwapOps,
TakerSwapMakerCoin, TradeFee, TradePreimageError, TradePreimageFut, TradePreimageResult,
TradePreimageValue, TransactionDetails, TransactionEnum, TransactionErr, TransactionFut, TransactionType,
TxMarshalingErr, UnexpectedDerivationMethod, ValidateAddressResult, ValidateFeeArgs,
ValidateInstructionsErr, ValidateOtherPubKeyErr, ValidatePaymentFut, ValidatePaymentInput,
VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps, WatcherReward, WatcherRewardError,
WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput, WatcherValidateTakerFeeInput,
WithdrawError, WithdrawFee, WithdrawFut, WithdrawRequest, WithdrawResult};
TradePreimageValue, TransactionDetails, TransactionEnum, TransactionErr, TransactionFut,
TransactionResult, TransactionType, TxMarshalingErr, UnexpectedDerivationMethod, ValidateAddressResult,
ValidateFeeArgs, ValidateInstructionsErr, ValidateOtherPubKeyErr, ValidatePaymentFut,
ValidatePaymentInput, VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps, WatcherReward,
WatcherRewardError, WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput,
WatcherValidateTakerFeeInput, WithdrawError, WithdrawFee, WithdrawFut, WithdrawRequest, WithdrawResult};
use async_trait::async_trait;
use bitcrypto::{dhash160, sha256};
use chain::TransactionOutput;
Expand Down Expand Up @@ -832,33 +832,23 @@ impl SwapOps for Qrc20Coin {
}

#[inline]
fn send_taker_refunds_payment(&self, taker_refunds_payment_args: RefundPaymentArgs) -> TransactionFut {
async fn send_taker_refunds_payment(&self, taker_refunds_payment_args: RefundPaymentArgs<'_>) -> TransactionResult {
let payment_tx: UtxoTx =
try_tx_fus!(deserialize(taker_refunds_payment_args.payment_tx).map_err(|e| ERRL!("{:?}", e)));
let swap_contract_address = try_tx_fus!(taker_refunds_payment_args.swap_contract_address.try_to_address());
try_tx_s!(deserialize(taker_refunds_payment_args.payment_tx).map_err(|e| ERRL!("{:?}", e)));
let swap_contract_address = try_tx_s!(taker_refunds_payment_args.swap_contract_address.try_to_address());

let selfi = self.clone();
let fut = async move {
selfi
.refund_hash_time_locked_payment(swap_contract_address, payment_tx)
.await
};
Box::new(fut.boxed().compat())
self.refund_hash_time_locked_payment(swap_contract_address, payment_tx)
.await
}

#[inline]
fn send_maker_refunds_payment(&self, maker_refunds_payment_args: RefundPaymentArgs) -> TransactionFut {
async fn send_maker_refunds_payment(&self, maker_refunds_payment_args: RefundPaymentArgs<'_>) -> TransactionResult {
let payment_tx: UtxoTx =
try_tx_fus!(deserialize(maker_refunds_payment_args.payment_tx).map_err(|e| ERRL!("{:?}", e)));
let swap_contract_address = try_tx_fus!(maker_refunds_payment_args.swap_contract_address.try_to_address());
try_tx_s!(deserialize(maker_refunds_payment_args.payment_tx).map_err(|e| ERRL!("{:?}", e)));
let swap_contract_address = try_tx_s!(maker_refunds_payment_args.swap_contract_address.try_to_address());

let selfi = self.clone();
let fut = async move {
selfi
.refund_hash_time_locked_payment(swap_contract_address, payment_tx)
.await
};
Box::new(fut.boxed().compat())
self.refund_hash_time_locked_payment(swap_contract_address, payment_tx)
.await
}

#[inline]
Expand Down
22 changes: 14 additions & 8 deletions mm2src/coins/solana.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use crate::{BalanceError, BalanceFut, CheckIfMyPaymentSentArgs, CoinFutSpawner,
RawTransactionFut, RawTransactionRequest, RefundError, RefundPaymentArgs, RefundResult,
SearchForSwapTxSpendInput, SendMakerPaymentSpendPreimageInput, SendPaymentArgs, SignatureResult,
SpendPaymentArgs, TakerSwapMakerCoin, TradePreimageFut, TradePreimageResult, TradePreimageValue,
TransactionDetails, TransactionFut, TransactionType, TxMarshalingErr, UnexpectedDerivationMethod,
ValidateAddressResult, ValidateFeeArgs, ValidateInstructionsErr, ValidateOtherPubKeyErr,
ValidatePaymentError, ValidatePaymentFut, ValidatePaymentInput, VerificationResult,
WaitForHTLCTxSpendArgs, WatcherReward, WatcherRewardError, WatcherSearchForSwapTxSpendInput,
WatcherValidatePaymentInput, WatcherValidateTakerFeeInput, WithdrawError, WithdrawFut, WithdrawRequest,
WithdrawResult};
TransactionDetails, TransactionFut, TransactionResult, TransactionType, TxMarshalingErr,
UnexpectedDerivationMethod, ValidateAddressResult, ValidateFeeArgs, ValidateInstructionsErr,
ValidateOtherPubKeyErr, ValidatePaymentError, ValidatePaymentFut, ValidatePaymentInput,
VerificationResult, WaitForHTLCTxSpendArgs, WatcherReward, WatcherRewardError,
WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput, WatcherValidateTakerFeeInput,
WithdrawError, WithdrawFut, WithdrawRequest, WithdrawResult};
use async_trait::async_trait;
use base58::ToBase58;
use bincode::{deserialize, serialize};
Expand Down Expand Up @@ -480,11 +480,17 @@ impl SwapOps for SolanaCoin {
unimplemented!()
}

fn send_taker_refunds_payment(&self, _taker_refunds_payment_args: RefundPaymentArgs) -> TransactionFut {
async fn send_taker_refunds_payment(
&self,
_taker_refunds_payment_args: RefundPaymentArgs<'_>,
) -> TransactionResult {
unimplemented!()
}

fn send_maker_refunds_payment(&self, _maker_refunds_payment_args: RefundPaymentArgs) -> TransactionFut {
async fn send_maker_refunds_payment(
&self,
_maker_refunds_payment_args: RefundPaymentArgs<'_>,
) -> TransactionResult {
unimplemented!()
}

Expand Down
Loading
Loading