Skip to content

Commit

Permalink
SLP and ARRR integration WIP #927 #701 (#954)
Browse files Browse the repository at this point in the history
* ARRR wip. Add dex_fee script with tests.

* WIP.

* Fix clippy.

* WIP. Demo of adding redeem script to the OP_RETURN.

* Add full redeem script to OP_RETURN of ARRR swap_payment_outputs.

* Fix tests compilation.

* WIP SLP OP_RETURN parsing.

* WIP adding ZAddrCoin.

* WIP implementing ZCoin. HTLC tx fails.

* Fix op_return for z_sendmany. HTLC broadcast worked.

* WIP zombie_coin_send_htlc_maker_payment success.

* WIP implementing HTLC refund.

* WIP trying to build transaction using pure Rust with librustzcash.

* WIP built and signed z output tx using pure rust, refactor.

* Fix WASM and clippy.

* WIP refactoring.

* WIP refactoring.

* WIP z_send_dex_fee

* WIP.

* WIP.

* WIP. Made the first RICK/ZOMBIE swap.

* Put ZCoin under zhtlc feature to avoid bundling Sapling params.

* Fix after merge.

* Fix WASM tests compilation.
  • Loading branch information
artemii235 authored May 28, 2021
1 parent d049502 commit 65d6d91
Show file tree
Hide file tree
Showing 11 changed files with 788 additions and 252 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ version = "0.1.0"
edition = "2018"
default-run = "mm2"

# Deprecated
[features]
# Deprecated
native = []
zhtlc = ["coins/zhtlc"]

[[bin]]
name = "mm2"
Expand Down
10 changes: 6 additions & 4 deletions mm2src/coins/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name = "coins"
version = "0.1.0"
edition = "2018"

[features]
zhtlc = ["zcash_client_backend", "zcash_primitives", "zcash_proofs"]

[lib]
name = "coins"
path = "lp_coins.rs"
Expand Down Expand Up @@ -77,7 +80,6 @@ rustls = { version = "0.18", features = ["dangerous_configuration"] }
tokio = { version = "0.2" }
tokio-rustls = { version = "0.14.1" }
webpki-roots = { version = "0.19.0" }
zcash_client_backend = { git = "https://github.com/KomodoPlatform/librustzcash.git" }
zcash_primitives = { features = ["transparent-inputs"], git = "https://github.com/KomodoPlatform/librustzcash.git" }
zcash_proofs = { features = ["bundled-prover"], git = "https://github.com/KomodoPlatform/librustzcash.git" }

zcash_client_backend = { git = "https://github.com/KomodoPlatform/librustzcash.git", optional = true }
zcash_primitives = { features = ["transparent-inputs"], git = "https://github.com/KomodoPlatform/librustzcash.git", optional = true }
zcash_proofs = { features = ["bundled-prover"], git = "https://github.com/KomodoPlatform/librustzcash.git", optional = true }
32 changes: 27 additions & 5 deletions mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ use qrc20::{qrc20_coin_from_conf_and_request, Qrc20Coin, Qrc20FeeDetails};
pub mod test_coin;
pub use test_coin::TestCoin;

pub mod tx_history_db;

#[cfg(not(target_arch = "wasm32"))] pub mod z_coin;
#[cfg(all(not(target_arch = "wasm32"), feature = "zhtlc"))]
pub mod z_coin;
#[cfg(all(not(target_arch = "wasm32"), feature = "zhtlc"))]
use z_coin::{z_coin_from_conf_and_request, ZCoin};

pub type BalanceResult<T> = Result<T, MmError<BalanceError>>;
pub type BalanceFut<T> = Box<dyn Future<Item = T, Error = MmError<BalanceError>> + Send>;
Expand Down Expand Up @@ -841,6 +842,8 @@ pub enum MmCoinEnum {
QtumCoin(QtumCoin),
Qrc20Coin(Qrc20Coin),
EthCoin(EthCoin),
#[cfg(all(not(target_arch = "wasm32"), feature = "zhtlc"))]
ZCoin(ZCoin),
Test(TestCoin),
}

Expand All @@ -864,6 +867,11 @@ impl From<Qrc20Coin> for MmCoinEnum {
fn from(c: Qrc20Coin) -> MmCoinEnum { MmCoinEnum::Qrc20Coin(c) }
}

#[cfg(all(not(target_arch = "wasm32"), feature = "zhtlc"))]
impl From<ZCoin> for MmCoinEnum {
fn from(c: ZCoin) -> MmCoinEnum { MmCoinEnum::ZCoin(c) }
}

// NB: When stable and groked by IDEs, `enum_dispatch` can be used instead of `Deref` to speed things up.
impl Deref for MmCoinEnum {
type Target = dyn MmCoin;
Expand All @@ -873,6 +881,8 @@ impl Deref for MmCoinEnum {
MmCoinEnum::QtumCoin(ref c) => c,
MmCoinEnum::Qrc20Coin(ref c) => c,
MmCoinEnum::EthCoin(ref c) => c,
#[cfg(all(not(target_arch = "wasm32"), feature = "zhtlc"))]
MmCoinEnum::ZCoin(ref c) => c,
MmCoinEnum::Test(ref c) => c,
}
}
Expand Down Expand Up @@ -906,9 +916,17 @@ impl CoinsContext {
pub enum CoinProtocol {
UTXO,
QTUM,
QRC20 { platform: String, contract_address: String },
QRC20 {
platform: String,
contract_address: String,
},
ETH,
ERC20 { platform: String, contract_address: String },
ERC20 {
platform: String,
contract_address: String,
},
#[cfg(all(not(target_arch = "wasm32"), feature = "zhtlc"))]
ZHTLC,
}

pub type RpcTransportEventHandlerShared = Arc<dyn RpcTransportEventHandler + Send + Sync + 'static>;
Expand Down Expand Up @@ -1114,6 +1132,8 @@ pub async fn lp_coininit(ctx: &MmArc, ticker: &str, req: &Json) -> Result<MmCoin
)
.into()
},
#[cfg(all(not(target_arch = "wasm32"), feature = "zhtlc"))]
CoinProtocol::ZHTLC => try_s!(z_coin_from_conf_and_request(ctx, ticker, &coins_en, req, secret).await).into(),
};

let block_count = try_s!(coin.current_block().compat().await);
Expand Down Expand Up @@ -1576,5 +1596,7 @@ pub fn address_by_coin_conf_and_pubkey_str(coin: &str, conf: &Json, pubkey: &str
CoinProtocol::UTXO | CoinProtocol::QTUM | CoinProtocol::QRC20 { .. } => {
utxo::address_by_conf_and_pubkey_str(coin, conf, pubkey)
},
#[cfg(all(not(target_arch = "wasm32"), feature = "zhtlc"))]
CoinProtocol::ZHTLC => utxo::address_by_conf_and_pubkey_str(coin, conf, pubkey),
}
}
63 changes: 42 additions & 21 deletions mm2src/coins/qrc20/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,19 +332,28 @@ impl Qrc20Coin {
let history_res = block_on(TransferHistoryBuilder::new(self.clone()).build_tx_idents());
let history = match history_res {
Ok(h) => h,
Err(e) => match &e.error {
JsonRpcErrorType::Transport(e) | JsonRpcErrorType::Parse(_, e) => {
Err(e) => match e.into_inner() {
UtxoRpcError::Transport(json_rpc_e) | UtxoRpcError::ResponseParseError(json_rpc_e) => {
match json_rpc_e.error {
JsonRpcErrorType::Response(_addr, err) => {
return if HISTORY_TOO_LARGE_ERROR.eq(&err) {
RequestTxHistoryResult::HistoryTooLarge
} else {
RequestTxHistoryResult::Retry {
error: ERRL!("Error {:?} on blockchain_contract_event_get_history", err),
}
}
},
JsonRpcErrorType::Transport(err) | JsonRpcErrorType::Parse(_, err) => {
return RequestTxHistoryResult::Retry {
error: ERRL!("Error {} on blockchain_contract_event_get_history", err),
};
},
}
},
UtxoRpcError::InvalidResponse(e) | UtxoRpcError::Internal(e) => {
return RequestTxHistoryResult::Retry {
error: ERRL!("Error {} on blockchain_contract_event_get_history", e),
};
},
JsonRpcErrorType::Response(_addr, err) => {
return if HISTORY_TOO_LARGE_ERROR.eq(err) {
RequestTxHistoryResult::HistoryTooLarge
} else {
RequestTxHistoryResult::Retry {
error: ERRL!("Error {:?} on blockchain_contract_event_get_history", e),
}
}
},
},
Expand Down Expand Up @@ -574,32 +583,38 @@ impl TransferHistoryBuilder {
self
}

pub async fn build(self) -> Result<Vec<TxReceipt>, JsonRpcError> {
pub async fn build(self) -> Result<Vec<TxReceipt>, MmError<UtxoRpcError>> {
self.coin.utxo.rpc_client.build(self.params).await
}

pub async fn build_tx_idents(self) -> Result<Vec<(H256Json, u64)>, JsonRpcError> {
pub async fn build_tx_idents(self) -> Result<Vec<(H256Json, u64)>, MmError<UtxoRpcError>> {
self.coin.utxo.rpc_client.build_tx_idents(self.params).await
}
}

#[async_trait]
trait BuildTransferHistory {
async fn build(&self, params: TransferHistoryParams) -> Result<Vec<TxReceipt>, JsonRpcError>;
async fn build(&self, params: TransferHistoryParams) -> Result<Vec<TxReceipt>, MmError<UtxoRpcError>>;

async fn build_tx_idents(&self, params: TransferHistoryParams) -> Result<Vec<(H256Json, u64)>, JsonRpcError>;
async fn build_tx_idents(
&self,
params: TransferHistoryParams,
) -> Result<Vec<(H256Json, u64)>, MmError<UtxoRpcError>>;
}

#[async_trait]
impl BuildTransferHistory for UtxoRpcClientEnum {
async fn build(&self, params: TransferHistoryParams) -> Result<Vec<TxReceipt>, JsonRpcError> {
async fn build(&self, params: TransferHistoryParams) -> Result<Vec<TxReceipt>, MmError<UtxoRpcError>> {
match self {
UtxoRpcClientEnum::Native(native) => native.build(params).await,
UtxoRpcClientEnum::Electrum(electrum) => electrum.build(params).await,
}
}

async fn build_tx_idents(&self, params: TransferHistoryParams) -> Result<Vec<(H256Json, u64)>, JsonRpcError> {
async fn build_tx_idents(
&self,
params: TransferHistoryParams,
) -> Result<Vec<(H256Json, u64)>, MmError<UtxoRpcError>> {
match self {
UtxoRpcClientEnum::Native(native) => native.build_tx_idents(params).await,
UtxoRpcClientEnum::Electrum(electrum) => electrum.build_tx_idents(params).await,
Expand All @@ -609,7 +624,7 @@ impl BuildTransferHistory for UtxoRpcClientEnum {

#[async_trait]
impl BuildTransferHistory for ElectrumClient {
async fn build(&self, params: TransferHistoryParams) -> Result<Vec<TxReceipt>, JsonRpcError> {
async fn build(&self, params: TransferHistoryParams) -> Result<Vec<TxReceipt>, MmError<UtxoRpcError>> {
let tx_idents = self.build_tx_idents(params).await?;

let mut receipts = Vec::new();
Expand All @@ -623,7 +638,10 @@ impl BuildTransferHistory for ElectrumClient {
Ok(receipts)
}

async fn build_tx_idents(&self, params: TransferHistoryParams) -> Result<Vec<(H256Json, u64)>, JsonRpcError> {
async fn build_tx_idents(
&self,
params: TransferHistoryParams,
) -> Result<Vec<(H256Json, u64)>, MmError<UtxoRpcError>> {
let address = contract_addr_into_rpc_format(&params.address);
let token_address = contract_addr_into_rpc_format(&params.token_address);
let history = self
Expand All @@ -642,7 +660,7 @@ impl BuildTransferHistory for ElectrumClient {

#[async_trait]
impl BuildTransferHistory for NativeClient {
async fn build(&self, params: TransferHistoryParams) -> Result<Vec<TxReceipt>, JsonRpcError> {
async fn build(&self, params: TransferHistoryParams) -> Result<Vec<TxReceipt>, MmError<UtxoRpcError>> {
const SEARCH_LOGS_STEP: u64 = 100;

let token_address = contract_addr_into_rpc_format(&params.token_address);
Expand Down Expand Up @@ -680,7 +698,10 @@ impl BuildTransferHistory for NativeClient {
Ok(result)
}

async fn build_tx_idents(&self, params: TransferHistoryParams) -> Result<Vec<(H256Json, u64)>, JsonRpcError> {
async fn build_tx_idents(
&self,
params: TransferHistoryParams,
) -> Result<Vec<(H256Json, u64)>, MmError<UtxoRpcError>> {
let receipts = self.build(params).await?;
Ok(receipts
.into_iter()
Expand Down
9 changes: 6 additions & 3 deletions mm2src/coins/qrc20/rpc_clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ pub trait Qrc20NativeOps {
to_block: Option<u64>,
addresses: Vec<H160Json>,
topics: Vec<TopicFilter>,
) -> RpcRes<Vec<TxReceipt>>;
) -> UtxoRpcFut<Vec<TxReceipt>>;
}

impl Qrc20NativeOps for NativeClient {
Expand All @@ -314,7 +314,7 @@ impl Qrc20NativeOps for NativeClient {
to_block: Option<u64>,
addresses: Vec<H160Json>,
topics: Vec<TopicFilter>,
) -> RpcRes<Vec<TxReceipt>> {
) -> UtxoRpcFut<Vec<TxReceipt>> {
let to_block = to_block.map(|x| x as i64).unwrap_or(-1);
let addr_block = json!({ "addresses": addresses });
let topics: Vec<Json> = topics
Expand All @@ -327,7 +327,10 @@ impl Qrc20NativeOps for NativeClient {
let topic_block = json!({
"topics": topics,
});
rpc_func!(self, "searchlogs", from_block, to_block, addr_block, topic_block)
Box::new(
rpc_func!(self, "searchlogs", from_block, to_block, addr_block, topic_block)
.map_to_mm_fut(UtxoRpcError::from),
)
}
}

Expand Down
27 changes: 21 additions & 6 deletions mm2src/coins/utxo/rpc_clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,13 @@ pub trait UtxoRpcClientOps: fmt::Debug + Send + Sync + 'static {

fn send_transaction(&self, tx: &UtxoTx) -> Box<dyn Future<Item = H256Json, Error = String> + Send + 'static>;

fn send_raw_transaction(&self, tx: BytesJson) -> RpcRes<H256Json>;
fn send_raw_transaction(&self, tx: BytesJson) -> UtxoRpcFut<H256Json>;

fn get_transaction_bytes(&self, txid: H256Json) -> UtxoRpcFut<BytesJson>;

fn get_verbose_transaction(&self, txid: H256Json) -> RpcRes<RpcTransaction>;

fn get_block_count(&self) -> RpcRes<u64>;
fn get_block_count(&self) -> UtxoRpcFut<u64>;

fn display_balance(&self, address: Address, decimals: u8) -> RpcRes<BigDecimal>;

Expand Down Expand Up @@ -569,7 +569,9 @@ impl UtxoRpcClientOps for NativeClient {
}

/// https://developer.bitcoin.org/reference/rpc/sendrawtransaction
fn send_raw_transaction(&self, tx: BytesJson) -> RpcRes<H256Json> { rpc_func!(self, "sendrawtransaction", tx) }
fn send_raw_transaction(&self, tx: BytesJson) -> UtxoRpcFut<H256Json> {
Box::new(rpc_func!(self, "sendrawtransaction", tx).map_to_mm_fut(UtxoRpcError::from))
}

fn get_transaction_bytes(&self, txid: H256Json) -> UtxoRpcFut<BytesJson> {
Box::new(self.get_raw_transaction_bytes(txid).map_to_mm_fut(UtxoRpcError::from))
Expand All @@ -579,7 +581,9 @@ impl UtxoRpcClientOps for NativeClient {
self.get_raw_transaction_verbose(txid)
}

fn get_block_count(&self) -> RpcRes<u64> { self.0.get_block_count() }
fn get_block_count(&self) -> UtxoRpcFut<u64> {
Box::new(self.0.get_block_count().map_to_mm_fut(UtxoRpcError::from))
}

fn display_balance(&self, address: Address, _decimals: u8) -> RpcRes<BigDecimal> {
Box::new(
Expand Down Expand Up @@ -1470,7 +1474,12 @@ impl UtxoRpcClientOps for ElectrumClient {
Box::new(self.blockchain_transaction_broadcast(bytes).map_err(|e| ERRL!("{}", e)))
}

fn send_raw_transaction(&self, tx: BytesJson) -> RpcRes<H256Json> { self.blockchain_transaction_broadcast(tx) }
fn send_raw_transaction(&self, tx: BytesJson) -> UtxoRpcFut<H256Json> {
Box::new(
self.blockchain_transaction_broadcast(tx)
.map_to_mm_fut(UtxoRpcError::from),
)
}

/// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-transaction-get
/// returns transaction bytes by default
Expand All @@ -1486,7 +1495,13 @@ impl UtxoRpcClientOps for ElectrumClient {
rpc_func!(self, "blockchain.transaction.get", txid, verbose)
}

fn get_block_count(&self) -> RpcRes<u64> { Box::new(self.blockchain_headers_subscribe().map(|r| r.block_height())) }
fn get_block_count(&self) -> UtxoRpcFut<u64> {
Box::new(
self.blockchain_headers_subscribe()
.map(|r| r.block_height())
.map_to_mm_fut(UtxoRpcError::from),
)
}

fn display_balance(&self, address: Address, decimals: u8) -> RpcRes<BigDecimal> {
let hash = electrum_script_hash(&Builder::build_p2pkh(&address.hash));
Expand Down
Loading

0 comments on commit 65d6d91

Please sign in to comment.