Skip to content

Commit

Permalink
Implement ARRR swap in light mode. #927 (#1302)
Browse files Browse the repository at this point in the history
* WIP. Fetched ZOMBIE compact blocks cache.

* WIP building wallet DB for ZOMBIE.

* WIP. Balance is shown incorrectly.

* WIP. Got correct balance for ZOMBIE address from lightwalletd.

* WIP.

* Sent shielded transaction using light mode.

* WIP.

* ZcoinLightClient WIP.

* WIP. Compilation fails. Saving dev state.

* WIP. Deleted some unneeded code.

* Cherry-pick from arrr-light-mode-experiments.

* WIP.

* WIP. Minor changes.

* WIP.

* WIP Zcoin light mode activation.

* WIP Activated ZOMBIE in light mode. Got correct balance.

* WIP. Working on withdraw.

* WIP. Optimized SQLite. Added withdraw ZOMBIE test.

* WIP. Got valid transaction from withdraw in light mode and broadcast it.

* WIP. Implementing light wallet sync state handling using channels.

* WIP. More refactoring.

* WIP.

* WIP.

* WIP. Compilation fails.

* WIP. Temporary Clippy fixes. Withdraw works.

* Fix WASM.

* WIP. Implementing state sync.

* WIP. Added SaplingSyncStateConnector.

* WIP. Added SaplingSyncRespawnHandle, SaplingSyncRespawnGuard, refactored SaplingSyncConnector.

* WIP. Did the first RICK/ZOMBIE light mode swap.

* WIP. Error handling.

* WIP. Error handling. Removed unused code.

* WIP. Trying AES.

* WIP. Deriving HTLC privkeys. Compilation fails.

* Finished HTLC privkeys derivation refactoring.

* WIP. Checking lightwalletd response when tx does not exist.

* Add watch_for_tx existence check in sync loop. Add ticker to activation response.

* Fix WASM.

* Fixes after merge.

* Change HTLC private keys derivation algo for Zcoin.

* Refactor to fix clippy::too_many_arguments.

* Fix tests.

* Replace block_in_place with async_blocking if required.

* Update tonic, remove some deps duplicates.

* WIP.

* Refactor tests a bit, ignore long-running ones.

* Disable blocks_cache_path for wasm32 arch.

* Fix tests compilation.

* More info about sync progress in init_z_coin_status.

* A bit more refactoring.

* Leave notes on how the light wallet state sync works.

* Last minor changes.

* Cargo.lock updated.

* Fix review notes.

* Fixes after merge.

* One more fix (udeps).

* Fix after merge.

* WIP. Fixing review notes.

* Use unique_swap_data() in try_spend_taker_payment.

* Fix review notes.

Co-authored-by: Artem Vitae <artem@vitae.com>
Co-authored-by: Artem Vitae <email@not.set>
  • Loading branch information
3 people authored Jun 14, 2022
1 parent dec68f5 commit 3be0c04
Show file tree
Hide file tree
Showing 53 changed files with 2,780 additions and 2,266 deletions.
324 changes: 185 additions & 139 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ debug-assertions = false
# For better or worse, might affect the stack traces in our portion of the code.
#opt-level = 1

[profile.test]
# required to avoid a long running process of librustcash additional chain validation that is enabled with debug assertions
debug-assertions = false

[profile.release.overrides."*"]
# Turns debugging symbols off for the out-of-workspace dependencies.
debug = false
Expand Down
11 changes: 2 additions & 9 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ skip = [
{ name = "ethereum-types", version = "*" },
{ name = "ff", version = "*" },
{ name = "fixed-hash", version = "*" },
{ name = "fixedbitset", version = "*" },
{ name = "fomat-macros", version = "*" },
{ name = "funty", version = "*" },
{ name = "futures", version = "*" },
Expand All @@ -214,7 +213,6 @@ skip = [
{ name = "group", version = "*" },
{ name = "hashbrown", version = "*" },
{ name = "hdrhistogram", version = "*" },
{ name = "heck", version = "*" },
{ name = "hex", version = "*" },
{ name = "hmac", version = "*" },
{ name = "http", version = "*" },
Expand Down Expand Up @@ -246,10 +244,6 @@ skip = [
{ name = "pin-project-lite", version = "*" },
{ name = "proc-macro-crate", version = "*" },
{ name = "proc-macro2", version = "*" },
{ name = "prost", version = "*" },
{ name = "prost-build", version = "*" },
{ name = "prost-derive", version = "*" },
{ name = "prost-types", version = "*" },
{ name = "quote", version = "*" },
{ name = "radium", version = "*" },
{ name = "rand", version = "*" },
Expand All @@ -263,6 +257,7 @@ skip = [
{ name = "rustc-hex", version = "*" },
{ name = "rustc_version", version = "*" },
{ name = "rustls", version = "*" },
{ name = "rustls-pemfile", version = "*" },
{ name = "scopeguard", version = "*" },
{ name = "sct", version = "*" },
{ name = "semver", version = "*" },
Expand All @@ -275,16 +270,14 @@ skip = [
{ name = "syn", version = "*" },
{ name = "time", version = "*" },
{ name = "tiny-keccak", version = "*" },
{ name = "tokio-rustls", version = "*" },
{ name = "trie-root", version = "*" },
{ name = "tokio-util", version = "*" },
{ name = "trie-root", version = "*" },
{ name = "uint", version = "*" },
{ name = "unicode-xid", version = "*" },
{ name = "unsigned-varint", version = "*" },
{ name = "url", version = "*" },
{ name = "wasi", version = "*" },
{ name = "webpki", version = "*" },
{ name = "webpki-roots", version = "*" },
{ name = "wyz", version = "*" },
]
# Similarly to `skip` allows you to skip certain crates during duplicate
Expand Down
9 changes: 6 additions & 3 deletions mm2src/coins/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ bytes = "0.4"
cfg-if = "1.0"
chain = { path = "../mm2_bitcoin/chain" }
common = { path = "../common" }
crossbeam = "0.7"
crypto = { path = "../crypto" }
db_common = { path = "../db_common" }
derive_more = "0.99"
Expand Down Expand Up @@ -62,7 +63,8 @@ mocktopus = "0.7.0"
num-traits = "0.2"
parking_lot = { version = "0.12.0", features = ["nightly"] }
primitives = { path = "../mm2_bitcoin/primitives" }
prost = "0.8"
prost = "0.10"
protobuf = "2.20"
rand = { version = "0.7", features = ["std", "small_rng"] }
rlp = { git = "https://github.com/artemii235/parity-common" }
rmp-serde = "0.14.3"
Expand Down Expand Up @@ -104,14 +106,15 @@ rust-ini = { version = "0.13" }
rustls = { version = "0.20", features = ["dangerous_configuration"] }
tokio = { version = "1.7" }
tokio-rustls = { version = "0.23" }
tonic = { version = "0.5.2", features = ["tls", "compression"] }
tonic = { version = "0.7", features = ["tls", "tls-webpki-roots", "compression"] }
webpki-roots = { version = "0.22" }
solana-client = { version = "1", default-features = false }
solana-sdk = { version = "1", default-features = false }
solana-transaction-status = "1"
spl-token = { version = "3" }
spl-associated-token-account = "1"
zcash_client_backend = { git = "https://github.com/KomodoPlatform/librustzcash.git" }
zcash_client_sqlite = { git = "https://github.com/KomodoPlatform/librustzcash.git" }
zcash_primitives = { features = ["transparent-inputs"], git = "https://github.com/KomodoPlatform/librustzcash.git" }
zcash_proofs = { git = "https://github.com/KomodoPlatform/librustzcash.git" }

Expand All @@ -123,4 +126,4 @@ mm2_test_helpers = { path = "../mm2_test_helpers" }

[build-dependencies]
prost-build = { version = "0.10.3", default-features = false }
tonic-build = { version = "0.5.2", features = ["prost", "compression"] }
tonic-build = { version = "0.7", features = ["prost", "compression"] }
101 changes: 55 additions & 46 deletions mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ pub use ethcore_transaction::SignedTransaction as SignedEthTx;
pub use rlp;

mod web3_transport;
use crate::{AsyncMutex, TransactionErr, TransactionFut, ValidatePaymentInput};
use crate::{AsyncMutex, SearchForSwapTxSpendInput, TransactionErr, TransactionFut, ValidatePaymentInput};
use common::mm_number::MmNumber;
use crypto::privkey::key_pair_from_secret;
use ethkey::{sign, verify_address};
use serialization::{CompactInteger, Serializable, Stream};
use web3_transport::{EthFeeHistoryNamespace, Web3Transport};
Expand Down Expand Up @@ -515,7 +516,7 @@ impl EthCoinImpl {
swap_contract_address: Address,
from_block: u64,
to_block: u64,
) -> Box<dyn Future<Item = Vec<Log>, Error = String>> {
) -> Box<dyn Future<Item = Vec<Log>, Error = String> + Send> {
let contract_event = try_fus!(SWAP_CONTRACT.event("SenderRefunded"));
let filter = FilterBuilder::default()
.topics(Some(vec![contract_event.signature()]), None, None, None)
Expand Down Expand Up @@ -692,11 +693,11 @@ impl SwapOps for EthCoin {
fn send_maker_payment(
&self,
time_lock: u32,
_maker_pub: &[u8],
taker_pub: &[u8],
secret_hash: &[u8],
amount: BigDecimal,
swap_contract_address: &Option<BytesJson>,
_swap_unique_data: &[u8],
) -> TransactionFut {
let taker_addr = try_tx_fus!(addr_from_raw_pubkey(taker_pub));
let swap_contract_address = try_tx_fus!(swap_contract_address.try_to_address());
Expand All @@ -717,11 +718,11 @@ impl SwapOps for EthCoin {
fn send_taker_payment(
&self,
time_lock: u32,
_taker_pub: &[u8],
maker_pub: &[u8],
secret_hash: &[u8],
amount: BigDecimal,
swap_contract_address: &Option<BytesJson>,
_swap_unique_data: &[u8],
) -> TransactionFut {
let maker_addr = try_tx_fus!(addr_from_raw_pubkey(maker_pub));
let swap_contract_address = try_tx_fus!(swap_contract_address.try_to_address());
Expand All @@ -745,8 +746,8 @@ impl SwapOps for EthCoin {
_time_lock: u32,
_taker_pub: &[u8],
secret: &[u8],
_htlc_privkey: &[u8],
swap_contract_address: &Option<BytesJson>,
_swap_unique_data: &[u8],
) -> TransactionFut {
let tx: UnverifiedTransaction = try_tx_fus!(rlp::decode(taker_payment_tx));
let signed = try_tx_fus!(SignedEthTx::new(tx));
Expand All @@ -764,8 +765,8 @@ impl SwapOps for EthCoin {
_time_lock: u32,
_maker_pub: &[u8],
secret: &[u8],
_htlc_privkey: &[u8],
swap_contract_address: &Option<BytesJson>,
_swap_unique_data: &[u8],
) -> TransactionFut {
let tx: UnverifiedTransaction = try_tx_fus!(rlp::decode(maker_payment_tx));
let signed = try_tx_fus!(SignedEthTx::new(tx));
Expand All @@ -782,8 +783,8 @@ impl SwapOps for EthCoin {
_time_lock: u32,
_maker_pub: &[u8],
_secret_hash: &[u8],
_htlc_privkey: &[u8],
swap_contract_address: &Option<BytesJson>,
_swap_unique_data: &[u8],
) -> TransactionFut {
let tx: UnverifiedTransaction = try_tx_fus!(rlp::decode(taker_payment_tx));
let signed = try_tx_fus!(SignedEthTx::new(tx));
Expand All @@ -801,8 +802,8 @@ impl SwapOps for EthCoin {
_time_lock: u32,
_taker_pub: &[u8],
_secret_hash: &[u8],
_htlc_privkey: &[u8],
swap_contract_address: &Option<BytesJson>,
_swap_unique_data: &[u8],
) -> TransactionFut {
let tx: UnverifiedTransaction = try_tx_fus!(rlp::decode(maker_payment_tx));
let signed = try_tx_fus!(SignedEthTx::new(tx));
Expand Down Expand Up @@ -926,7 +927,7 @@ impl SwapOps for EthCoin {
self.validate_payment(
&input.payment_tx,
input.time_lock,
&input.maker_pub,
&input.other_pub,
&input.secret_hash,
input.amount,
swap_contract_address,
Expand All @@ -938,7 +939,7 @@ impl SwapOps for EthCoin {
self.validate_payment(
&input.payment_tx,
input.time_lock,
&input.taker_pub,
&input.other_pub,
&input.secret_hash,
input.amount,
swap_contract_address,
Expand All @@ -948,11 +949,11 @@ impl SwapOps for EthCoin {
fn check_if_my_payment_sent(
&self,
time_lock: u32,
_my_pub: &[u8],
_other_pub: &[u8],
secret_hash: &[u8],
from_block: u64,
swap_contract_address: &Option<BytesJson>,
_swap_unique_data: &[u8],
) -> Box<dyn Future<Item = Option<TransactionEnum>, Error = String> + Send> {
let id = self.etomic_swap_id(time_lock, secret_hash);
let swap_contract_address = try_fus!(swap_contract_address.try_to_address());
Expand Down Expand Up @@ -1017,28 +1018,20 @@ impl SwapOps for EthCoin {

async fn search_for_swap_tx_spend_my(
&self,
_time_lock: u32,
_other_pub: &[u8],
_secret_hash: &[u8],
tx: &[u8],
search_from_block: u64,
swap_contract_address: &Option<BytesJson>,
input: SearchForSwapTxSpendInput<'_>,
) -> Result<Option<FoundSwapTxSpend>, String> {
let swap_contract_address = try_s!(swap_contract_address.try_to_address());
self.search_for_swap_tx_spend(tx, swap_contract_address, search_from_block)
let swap_contract_address = try_s!(input.swap_contract_address.try_to_address());
self.search_for_swap_tx_spend(input.tx, swap_contract_address, input.search_from_block)
.await
}

async fn search_for_swap_tx_spend_other(
&self,
_time_lock: u32,
_other_pub: &[u8],
_secret_hash: &[u8],
tx: &[u8],
search_from_block: u64,
swap_contract_address: &Option<BytesJson>,
input: SearchForSwapTxSpendInput<'_>,
) -> Result<Option<FoundSwapTxSpend>, String> {
let swap_contract_address = try_s!(swap_contract_address.try_to_address());
self.search_for_swap_tx_spend(tx, swap_contract_address, search_from_block)
let swap_contract_address = try_s!(input.swap_contract_address.try_to_address());
self.search_for_swap_tx_spend(input.tx, swap_contract_address, input.search_from_block)
.await
}

fn extract_secret(&self, _secret_hash: &[u8], spend_tx: &[u8]) -> Result<Vec<u8>, String> {
Expand Down Expand Up @@ -1083,7 +1076,9 @@ impl SwapOps for EthCoin {
}
}

fn get_htlc_key_pair(&self) -> Option<keys::KeyPair> { None }
fn derive_htlc_key_pair(&self, _swap_unique_data: &[u8]) -> keys::KeyPair {
key_pair_from_secret(self.key_pair.secret()).expect("valid key")
}
}

#[cfg_attr(test, mockable)]
Expand Down Expand Up @@ -2785,7 +2780,7 @@ impl EthCoin {
)
}

fn search_for_swap_tx_spend(
async fn search_for_swap_tx_spend(
&self,
tx: &[u8],
swap_contract_address: Address,
Expand All @@ -2806,7 +2801,7 @@ impl EthCoin {
_ => panic!(),
};

let mut current_block = try_s!(self.current_block().wait());
let mut current_block = try_s!(self.current_block().compat().await);
if current_block < search_from_block {
current_block = search_from_block;
}
Expand All @@ -2816,19 +2811,26 @@ impl EthCoin {
loop {
let to_block = current_block.min(from_block + self.logs_block_range);

let spend_events = try_s!(self.spend_events(swap_contract_address, from_block, to_block).wait());
let spend_events = try_s!(
self.spend_events(swap_contract_address, from_block, to_block)
.compat()
.await
);
let found = spend_events.iter().find(|event| &event.data.0[..32] == id.as_slice());

if let Some(event) = found {
match event.transaction_hash {
Some(tx_hash) => {
let transaction = match try_s!(self.web3.eth().transaction(TransactionId::Hash(tx_hash)).wait())
{
Some(t) => t,
None => {
return ERR!("Found ReceiverSpent event, but transaction {:02x} is missing", tx_hash)
},
};
let transaction =
match try_s!(self.web3.eth().transaction(TransactionId::Hash(tx_hash)).compat().await) {
Some(t) => t,
None => {
return ERR!(
"Found ReceiverSpent event, but transaction {:02x} is missing",
tx_hash
)
},
};

return Ok(Some(FoundSwapTxSpend::Spent(TransactionEnum::from(try_s!(
signed_tx_from_web3_tx(transaction)
Expand All @@ -2838,19 +2840,26 @@ impl EthCoin {
}
}

let refund_events = try_s!(self.refund_events(swap_contract_address, from_block, to_block).wait());
let refund_events = try_s!(
self.refund_events(swap_contract_address, from_block, to_block)
.compat()
.await
);
let found = refund_events.iter().find(|event| &event.data.0[..32] == id.as_slice());

if let Some(event) = found {
match event.transaction_hash {
Some(tx_hash) => {
let transaction = match try_s!(self.web3.eth().transaction(TransactionId::Hash(tx_hash)).wait())
{
Some(t) => t,
None => {
return ERR!("Found SenderRefunded event, but transaction {:02x} is missing", tx_hash)
},
};
let transaction =
match try_s!(self.web3.eth().transaction(TransactionId::Hash(tx_hash)).compat().await) {
Some(t) => t,
None => {
return ERR!(
"Found SenderRefunded event, but transaction {:02x} is missing",
tx_hash
)
},
};

return Ok(Some(FoundSwapTxSpend::Refunded(TransactionEnum::from(try_s!(
signed_tx_from_web3_tx(transaction)
Expand Down
Loading

0 comments on commit 3be0c04

Please sign in to comment.