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): sql storage wip + protocol enhancement #1980

Merged
merged 35 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0713b5f
Removing access by index.
artemii235 Sep 12, 2023
e638c5b
Removing access by index.
artemii235 Sep 13, 2023
72e25a4
WIP. SQLite storage for swaps.
artemii235 Sep 14, 2023
530725f
WIP. SQLite storage for swaps.
artemii235 Sep 14, 2023
3377afe
WIP. SQLite storage.
artemii235 Sep 15, 2023
1c9442b
WIP. SQLite storage for upgraded swaps.
artemii235 Sep 18, 2023
ca53aa2
WIP. Additional validation.
artemii235 Sep 18, 2023
3c1cf64
WIP. Additional validation and refactoring.
artemii235 Sep 19, 2023
c49d424
WIP. Additional validation and refactoring.
artemii235 Sep 20, 2023
137988c
WIP. Refactor a bit.
artemii235 Sep 22, 2023
d8a9608
WIP. Refactor.
artemii235 Sep 25, 2023
596fc22
WIP. Protocol enhancement.
Sep 26, 2023
c4a8c68
WIP. Protocol enhancement.
Sep 26, 2023
fffab29
WIP. Protocol enhancement.
Sep 26, 2023
6c6c86f
WIP. Protocol enhancement.
Sep 26, 2023
01670f7
WIP. Demo of maker trying to use taker preimage signature for refund …
artemii235 Sep 27, 2023
b7c327a
WIP. Protocol enhancement.
artemii235 Sep 27, 2023
c6805d3
WIP. Protocol enhancement.
artemii235 Sep 28, 2023
b3cc12f
WIP. Protocol enhancement.
artemii235 Sep 28, 2023
89f6185
WIP. Made successful swap after enhancement.
artemii235 Sep 29, 2023
eee4470
WIP. Added validate_taker_funding.
artemii235 Sep 29, 2023
5bdb141
WIP. Started addition of validate_taker_funding_spend_preimage.
Sep 29, 2023
987c50d
WIP. Implementing validate_taker_funding_spend_preimage.
artemii235 Oct 2, 2023
122464c
WIP. Finish validate_taker_funding_spend_preimage for UTXO coins.
artemii235 Oct 2, 2023
eb0aa7d
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Oct 2, 2023
92990cb
Temporary disable upgraded swaps under WASM.
artemii235 Oct 2, 2023
909456e
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Oct 2, 2023
47f4160
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
Oct 4, 2023
c18a597
Fix imports after merging with dev.
Oct 4, 2023
c3c527c
Review fixes.
Oct 4, 2023
7697d24
Review fixes: use named_params macro.
artemii235 Oct 5, 2023
f197ffb
Wait for taker payment conf instead of funding.
artemii235 Oct 6, 2023
e26203f
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Oct 26, 2023
628e568
Merge remote-tracking branch 'origin/dev' into swap-proto-upgrade-ite…
artemii235 Oct 30, 2023
9de1ea2
Fixes after syncing with dev.
artemii235 Oct 30, 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
230 changes: 175 additions & 55 deletions mm2src/coins/lp_coins.rs

Large diffs are not rendered by default.

121 changes: 101 additions & 20 deletions mm2src/coins/test_coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@

use super::{CoinBalance, HistorySyncState, MarketCoinOps, MmCoin, RawTransactionFut, RawTransactionRequest, SwapOps,
TradeFee, TransactionEnum, TransactionFut};
use crate::{coin_errors::MyAddressError, BalanceFut, CanRefundHtlc, CheckIfMyPaymentSentArgs, CoinFutSpawner,
ConfirmPaymentInput, FeeApproxStage, FoundSwapTxSpend, GenTakerPaymentSpendArgs,
GenTakerPaymentSpendResult, MakerSwapTakerCoin, MmCoinEnum, NegotiateSwapContractAddrErr,
PaymentInstructionArgs, PaymentInstructions, PaymentInstructionsErr, RefundPaymentArgs, RefundResult,
SearchForSwapTxSpendInput, SendCombinedTakerPaymentArgs, SendMakerPaymentSpendPreimageInput,
SendPaymentArgs, SignatureResult, SpendPaymentArgs, SwapOpsV2, TakerSwapMakerCoin, TradePreimageFut,
TradePreimageResult, TradePreimageValue, TransactionResult, TxMarshalingErr, TxPreimageWithSig,
use crate::{coin_errors::MyAddressError, BalanceFut, CanRefundHtlc, CheckIfMyPaymentSentArgs, CoinAssocTypes,
CoinFutSpawner, ConfirmPaymentInput, FeeApproxStage, FoundSwapTxSpend, GenPreimageResult,
GenTakerFundingSpendArgs, GenTakerPaymentSpendArgs, MakerSwapTakerCoin, MmCoinEnum,
NegotiateSwapContractAddrErr, PaymentInstructionArgs, PaymentInstructions, PaymentInstructionsErr,
RefundFundingSecretArgs, RefundPaymentArgs, RefundResult, SearchForSwapTxSpendInput,
SendMakerPaymentSpendPreimageInput, SendPaymentArgs, SendTakerFundingArgs, SignatureResult,
SpendPaymentArgs, SwapOpsV2, TakerSwapMakerCoin, ToBytes, TradePreimageFut, TradePreimageResult,
TradePreimageValue, Transaction, TransactionErr, TransactionResult, TxMarshalingErr, TxPreimageWithSig,
UnexpectedDerivationMethod, ValidateAddressResult, ValidateFeeArgs, ValidateInstructionsErr,
ValidateOtherPubKeyErr, ValidatePaymentError, ValidatePaymentFut, ValidatePaymentInput,
ValidateTakerPaymentArgs, ValidateTakerPaymentResult, ValidateTakerPaymentSpendPreimageResult,
VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps, WatcherReward, WatcherRewardError,
WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput, WatcherValidateTakerFeeInput, WithdrawFut,
WithdrawRequest};
ValidateTakerFundingArgs, ValidateTakerFundingResult, ValidateTakerFundingSpendPreimageResult,
ValidateTakerPaymentSpendPreimageResult, VerificationResult, WaitForHTLCTxSpendArgs, WatcherOps,
WatcherReward, WatcherRewardError, WatcherSearchForSwapTxSpendInput, WatcherValidatePaymentInput,
WatcherValidateTakerFeeInput, WithdrawFut, WithdrawRequest};
use async_trait::async_trait;
use common::executor::AbortedError;
use futures01::Future;
Expand Down Expand Up @@ -382,42 +383,122 @@ impl MmCoin for TestCoin {
fn on_token_deactivated(&self, _ticker: &str) { () }
}

pub struct TestPubkey {}

impl ToBytes for TestPubkey {
fn to_bytes(&self) -> Vec<u8> { vec![] }
}

#[derive(Debug)]
pub struct TestTx {}

impl Transaction for TestTx {
fn tx_hex(&self) -> Vec<u8> { todo!() }

fn tx_hash(&self) -> BytesJson { todo!() }
}

pub struct TestPreimage {}

impl ToBytes for TestPreimage {
fn to_bytes(&self) -> Vec<u8> { vec![] }
}

pub struct TestSig {}

impl ToBytes for TestSig {
fn to_bytes(&self) -> Vec<u8> { vec![] }
}

impl CoinAssocTypes for TestCoin {
type Pubkey = TestPubkey;
type PubkeyParseError = String;
type Tx = TestTx;
type TxParseError = String;
type Preimage = TestPreimage;
type PreimageParseError = String;
type Sig = TestSig;
type SigParseError = String;

fn parse_pubkey(&self, pubkey: &[u8]) -> Result<Self::Pubkey, Self::PubkeyParseError> { unimplemented!() }

fn parse_tx(&self, tx: &[u8]) -> Result<Self::Tx, Self::TxParseError> { unimplemented!() }

fn parse_preimage(&self, preimage: &[u8]) -> Result<Self::Preimage, Self::PreimageParseError> { todo!() }

fn parse_signature(&self, sig: &[u8]) -> Result<Self::Sig, Self::SigParseError> { todo!() }
}

#[async_trait]
#[mockable]
impl SwapOpsV2 for TestCoin {
async fn send_combined_taker_payment(&self, args: SendCombinedTakerPaymentArgs<'_>) -> TransactionResult {
async fn send_taker_funding(&self, args: SendTakerFundingArgs<'_>) -> Result<Self::Tx, TransactionErr> { todo!() }

async fn validate_taker_funding(&self, args: ValidateTakerFundingArgs<'_, Self>) -> ValidateTakerFundingResult {
unimplemented!()
}

async fn validate_combined_taker_payment(&self, args: ValidateTakerPaymentArgs<'_>) -> ValidateTakerPaymentResult {
unimplemented!()
async fn refund_taker_funding_timelock(&self, args: RefundPaymentArgs<'_>) -> TransactionResult { todo!() }

async fn refund_taker_funding_secret(
&self,
args: RefundFundingSecretArgs<'_, Self>,
) -> Result<Self::Tx, TransactionErr> {
todo!()
}

async fn gen_taker_funding_spend_preimage(
&self,
args: &GenTakerFundingSpendArgs<'_, Self>,
swap_unique_data: &[u8],
) -> GenPreimageResult<Self> {
todo!()
}

async fn validate_taker_funding_spend_preimage(
&self,
gen_args: &GenTakerFundingSpendArgs<'_, Self>,
preimage: &TxPreimageWithSig<Self>,
) -> ValidateTakerFundingSpendPreimageResult {
todo!()
}

async fn sign_and_send_taker_funding_spend(
&self,
preimage: &TxPreimageWithSig<Self>,
args: &GenTakerFundingSpendArgs<'_, Self>,
swap_unique_data: &[u8],
) -> Result<Self::Tx, TransactionErr> {
todo!()
}

async fn refund_combined_taker_payment(&self, args: RefundPaymentArgs<'_>) -> TransactionResult { unimplemented!() }

async fn gen_taker_payment_spend_preimage(
&self,
args: &GenTakerPaymentSpendArgs<'_>,
args: &GenTakerPaymentSpendArgs<'_, Self>,
swap_unique_data: &[u8],
) -> GenTakerPaymentSpendResult {
) -> GenPreimageResult<Self> {
unimplemented!()
}

async fn validate_taker_payment_spend_preimage(
&self,
gen_args: &GenTakerPaymentSpendArgs<'_>,
preimage: &TxPreimageWithSig,
gen_args: &GenTakerPaymentSpendArgs<'_, Self>,
preimage: &TxPreimageWithSig<Self>,
) -> ValidateTakerPaymentSpendPreimageResult {
unimplemented!()
}

async fn sign_and_broadcast_taker_payment_spend(
&self,
preimage: &TxPreimageWithSig,
gen_args: &GenTakerPaymentSpendArgs<'_>,
preimage: &TxPreimageWithSig<Self>,
gen_args: &GenTakerPaymentSpendArgs<'_, Self>,
secret: &[u8],
swap_unique_data: &[u8],
) -> TransactionResult {
unimplemented!()
}

fn derive_htlc_pubkey_v2(&self, swap_unique_data: &[u8]) -> Self::Pubkey { todo!() }
}
44 changes: 43 additions & 1 deletion mm2src/coins/utxo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ use futures::compat::Future01CompatExt;
use futures::lock::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard};
use futures01::Future;
use keys::bytes::Bytes;
use keys::Signature;
pub use keys::{Address, AddressFormat as UtxoAddressFormat, AddressHashEnum, KeyPair, Private, Public, Secret,
Type as ScriptType};
#[cfg(not(target_arch = "wasm32"))]
Expand All @@ -74,8 +75,9 @@ use num_traits::ToPrimitive;
use primitives::hash::{H160, H256, H264};
use rpc::v1::types::{Bytes as BytesJson, Transaction as RpcTransaction, H256 as H256Json};
use script::{Builder, Script, SignatureVersion, TransactionInputSigner};
use secp256k1::Signature as SecpSignature;
use serde_json::{self as json, Value as Json};
use serialization::{serialize, serialize_with_flags, Error as SerError, SERIALIZE_TRANSACTION_WITNESS};
use serialization::{deserialize, serialize, serialize_with_flags, Error as SerError, SERIALIZE_TRANSACTION_WITNESS};
use spv_validation::conf::SPVConf;
use spv_validation::helpers_validation::SPVError;
use spv_validation::storage::BlockHeaderStorageError;
Expand Down Expand Up @@ -110,6 +112,7 @@ use crate::hd_wallet::{HDAccountOps, HDAccountsMutex, HDAddress, HDAddressId, HD
InvalidBip44ChainError};
use crate::hd_wallet_storage::{HDAccountStorageItem, HDWalletCoinStorage, HDWalletStorageError, HDWalletStorageResult};
use crate::utxo::tx_cache::UtxoVerboseCacheShared;
use crate::{CoinAssocTypes, ToBytes};

pub mod tx_cache;

Expand Down Expand Up @@ -1011,6 +1014,45 @@ pub trait UtxoCommonOps:
}
}

impl ToBytes for UtxoTx {
fn to_bytes(&self) -> Vec<u8> { self.tx_hex() }
}

impl ToBytes for Signature {
fn to_bytes(&self) -> Vec<u8> { self.to_vec() }
}

impl<T: UtxoCommonOps> CoinAssocTypes for T {
type Pubkey = Public;
type PubkeyParseError = MmError<keys::Error>;
type Tx = UtxoTx;
type TxParseError = MmError<serialization::Error>;
type Preimage = UtxoTx;
type PreimageParseError = MmError<serialization::Error>;
type Sig = Signature;
type SigParseError = MmError<secp256k1::Error>;

#[inline]
fn parse_pubkey(&self, pubkey: &[u8]) -> Result<Self::Pubkey, Self::PubkeyParseError> {
Ok(Public::from_slice(pubkey)?)
}

#[inline]
fn parse_tx(&self, tx: &[u8]) -> Result<Self::Tx, Self::TxParseError> {
let mut tx: UtxoTx = deserialize(tx)?;
tx.tx_hash_algo = self.as_ref().tx_hash_algo;
Ok(tx)
}

#[inline]
fn parse_preimage(&self, tx: &[u8]) -> Result<Self::Preimage, Self::PreimageParseError> { self.parse_tx(tx) }

fn parse_signature(&self, sig: &[u8]) -> Result<Self::Sig, Self::SigParseError> {
SecpSignature::from_der(sig)?;
Ok(sig.into())
}
}

#[async_trait]
#[cfg_attr(test, mockable)]
pub trait GetUtxoListOps {
Expand Down
70 changes: 56 additions & 14 deletions mm2src/coins/utxo/swap_proto_v2_scripts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,79 @@ use bitcrypto::ripemd160;
use keys::Public;
use script::{Builder, Opcode, Script};

/// Builds a script for refundable dex_fee + premium taker transaction
pub fn taker_payment_script(time_lock: u32, secret_hash: &[u8], pub_0: &Public, pub_1: &Public) -> Script {
/// Builds a script for taker funding transaction
pub fn taker_funding_script(
time_lock: u32,
taker_secret_hash: &[u8],
taker_pub: &Public,
maker_pub: &Public,
) -> Script {
let mut builder = Builder::default()
// Dex fee refund path, same lock time as for taker payment
.push_opcode(Opcode::OP_IF)
.push_bytes(&time_lock.to_le_bytes())
.push_opcode(Opcode::OP_CHECKLOCKTIMEVERIFY)
.push_opcode(Opcode::OP_DROP)
.push_bytes(pub_0)
.push_bytes(taker_pub)
.push_opcode(Opcode::OP_CHECKSIG)
.push_opcode(Opcode::OP_ELSE)
.push_opcode(Opcode::OP_IF)
.push_bytes(taker_pub)
.push_opcode(Opcode::OP_CHECKSIGVERIFY)
.push_bytes(maker_pub)
.push_opcode(Opcode::OP_CHECKSIG)
// Dex fee redeem path, Maker needs to reveal the secret to prevent case of getting
// the premium but not proceeding with spending the taker payment
.push_opcode(Opcode::OP_ELSE)
.push_opcode(Opcode::OP_SIZE)
.push_bytes(&[32])
.push_opcode(Opcode::OP_EQUALVERIFY)
.push_opcode(Opcode::OP_HASH160);

if secret_hash.len() == 32 {
builder = builder.push_bytes(ripemd160(secret_hash).as_slice());
if taker_secret_hash.len() == 32 {
builder = builder.push_bytes(ripemd160(taker_secret_hash).as_slice());
} else {
builder = builder.push_bytes(secret_hash);
builder = builder.push_bytes(taker_secret_hash);
}

builder
.push_opcode(Opcode::OP_EQUALVERIFY)
.push_opcode(Opcode::OP_2)
.push_bytes(pub_0)
.push_bytes(pub_1)
.push_opcode(Opcode::OP_2)
.push_opcode(Opcode::OP_CHECKMULTISIG)
.push_bytes(taker_pub)
.push_opcode(Opcode::OP_CHECKSIG)
.push_opcode(Opcode::OP_ENDIF)
.push_opcode(Opcode::OP_ENDIF)
.into_script()
}

/// Builds a script for combined trading_volume + dex_fee + premium taker transaction
pub fn taker_payment_script(
time_lock: u32,
maker_secret_hash: &[u8],
taker_pub: &Public,
maker_pub: &Public,
) -> Script {
let mut builder = Builder::default()
.push_opcode(Opcode::OP_IF)
.push_bytes(&time_lock.to_le_bytes())
.push_opcode(Opcode::OP_CHECKLOCKTIMEVERIFY)
.push_opcode(Opcode::OP_DROP)
.push_bytes(taker_pub)
.push_opcode(Opcode::OP_CHECKSIG)
.push_opcode(Opcode::OP_ELSE)
.push_opcode(Opcode::OP_SIZE)
.push_bytes(&[32])
.push_opcode(Opcode::OP_EQUALVERIFY)
.push_opcode(Opcode::OP_HASH160);

if maker_secret_hash.len() == 32 {
builder = builder.push_bytes(ripemd160(maker_secret_hash).as_slice());
} else {
builder = builder.push_bytes(maker_secret_hash);
}

builder
.push_opcode(Opcode::OP_EQUALVERIFY)
.push_bytes(taker_pub)
.push_opcode(Opcode::OP_CHECKSIGVERIFY)
.push_bytes(maker_pub)
.push_opcode(Opcode::OP_CHECKSIG)
.push_opcode(Opcode::OP_ENDIF)
.into_script()
}
Loading
Loading