diff --git a/Cargo.lock b/Cargo.lock index a5e4ca39d..c2d4bf782 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -755,9 +755,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" @@ -1475,21 +1475,23 @@ checksum = "847e59bd6ee1c3f2bdf217118ee3640b97a1b1d8becb55771e67e533b87da66f" dependencies = [ "bitcoin 0.29.2", "log", + "reqwest", "serde", - "ureq", ] [[package]] name = "esplora-client" version = "0.6.0" -source = "git+https://github.com/bitcoindevkit/rust-esplora-client?rev=269360f#269360fb75bf24c8bed641c5906b0282fc3fcf84" +source = "git+https://github.com/get10101/rust-esplora-client?rev=24508f7#24508f7d5a06a9e2515afb9f78ec5946048f3289" dependencies = [ "bitcoin 0.30.2", "bitcoin-internals", + "bytes", "log", "reqwest", "serde", - "ureq", + "serde_json", + "tokio", ] [[package]] @@ -1641,9 +1643,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1651,9 +1653,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" @@ -1685,9 +1687,9 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" @@ -2058,6 +2060,19 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +dependencies = [ + "http 0.2.9", + "hyper 0.14.24", + "rustls 0.20.9", + "tokio", + "tokio-rustls 0.23.4", +] + [[package]] name = "hyper-timeout" version = "0.4.1" @@ -2224,9 +2239,9 @@ checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -2320,7 +2335,9 @@ dependencies = [ "bdk-macros", "bitcoin 0.29.2", "esplora-client 0.4.0", + "futures", "lightning", + "reqwest", ] [[package]] @@ -2343,7 +2360,6 @@ name = "ln-dlc-node" version = "0.1.0" dependencies = [ "anyhow", - "async-trait", "axum 0.6.20", "bdk", "bdk_coin_select", @@ -2376,16 +2392,17 @@ dependencies = [ "rust_decimal", "secp256k1-zkp", "serde", + "serde_json", "serde_with 3.2.0", "sha2", "thiserror", "time", "tokio", "tokio-tungstenite-wasm", + "tokio_with_wasm", "tracing", "tracing-log 0.1.3", "tracing-subscriber", - "ureq", "uuid", ] @@ -2928,11 +2945,12 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p2pd-oracle-client" version = "0.1.0" -source = "git+https://github.com/get10101/rust-dlc?rev=a569d3e#a569d3e83ab11d17084b707aeff9866fc1824884" +source = "git+https://github.com/get10101/rust-dlc/?rev=caba716#caba7163b2d8ef1f63ebccf932fec77ca996c4a1" dependencies = [ "chrono", "dlc-manager", "dlc-messages", + "pollster", "reqwest", "secp256k1-zkp", "serde", @@ -3065,6 +3083,12 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + [[package]] name = "polyval" version = "0.6.1" @@ -3390,6 +3414,7 @@ dependencies = [ "http 0.2.9", "http-body 0.4.5", "hyper 0.14.24", + "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -3399,11 +3424,14 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls 0.20.9", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", + "tokio-rustls 0.23.4", "tokio-socks", "tokio-util", "tower-service", @@ -3412,6 +3440,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg", ] @@ -3486,7 +3515,7 @@ dependencies = [ [[package]] name = "rust-bitcoin-coin-selection" version = "0.1.0" -source = "git+https://github.com/p2pderivatives/rust-bitcoin-coin-selection#405451929568422f7df809e35d6ad8f36fccce90" +source = "git+https://github.com/p2pderivatives/rust-bitcoin-coin-selection?rev=4054519#405451929568422f7df809e35d6ad8f36fccce90" dependencies = [ "rand", ] @@ -3582,6 +3611,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rustls" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +dependencies = [ + "log", + "ring 0.16.20", + "sct", + "webpki", +] + [[package]] name = "rustls" version = "0.21.7" @@ -3590,7 +3631,7 @@ checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ "log", "ring 0.16.20", - "rustls-webpki 0.101.4", + "rustls-webpki", "sct", ] @@ -3603,16 +3644,6 @@ dependencies = [ "base64 0.21.7", ] -[[package]] -name = "rustls-webpki" -version = "0.100.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - [[package]] name = "rustls-webpki" version = "0.101.4" @@ -3823,9 +3854,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -4004,17 +4035,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "socks" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" -dependencies = [ - "byteorder", - "libc", - "winapi", -] - [[package]] name = "spin" version = "0.5.2" @@ -4327,13 +4347,24 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.9", + "tokio", + "webpki", +] + [[package]] name = "tokio-rustls" version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.7", "tokio", ] @@ -4421,6 +4452,20 @@ dependencies = [ "tracing", ] +[[package]] +name = "tokio_with_wasm" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e6a955eb27969f01cdc13784eb46dbadda5f75dee2de887bd538ba987a87b8" +dependencies = [ + "futures-channel", + "js-sys", + "tokio", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "toml" version = "0.5.11" @@ -4833,25 +4878,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "ureq" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" -dependencies = [ - "base64 0.21.7", - "flate2", - "log", - "once_cell", - "rustls", - "rustls-webpki 0.100.2", - "serde", - "serde_json", - "socks", - "url", - "webpki-roots", -] - [[package]] name = "url" version = "2.4.1" @@ -4959,9 +4985,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4969,24 +4995,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.34" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -4996,9 +5022,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5006,22 +5032,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-streams" @@ -5038,9 +5064,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -5074,7 +5100,7 @@ dependencies = [ "sha2", "time", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", "tower", "tower-http", "tracing", @@ -5083,13 +5109,23 @@ dependencies = [ "uuid", ] +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.7", + "untrusted 0.9.0", +] + [[package]] name = "webpki-roots" -version = "0.23.1" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" dependencies = [ - "rustls-webpki 0.100.2", + "webpki", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1e94d0ae8..025215966 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ resolver = "2" dlc-manager = { git = "https://github.com/get10101/rust-dlc", rev = "a569d3e" } dlc-messages = { git = "https://github.com/get10101/rust-dlc", rev = "a569d3e" } dlc = { git = "https://github.com/get10101/rust-dlc", rev = "a569d3e" } -p2pd-oracle-client = { git = "https://github.com/get10101/rust-dlc", rev = "a569d3e" } +p2pd-oracle-client = { git = "https://github.com/get10101/rust-dlc/", rev = "caba716" } dlc-trie = { git = "https://github.com/get10101/rust-dlc", rev = "a569d3e" } # We should usually track the `p2pderivatives/split-tx-experiment[-10101]` branch. For now we depend @@ -33,9 +33,8 @@ lightning-background-processor = { git = "https://github.com/bonomat/rust-lightn lightning-transaction-sync = { git = "https://github.com/bonomat/rust-lightning-p2p-derivatives", rev = "e49030e" } lightning-persister = { git = "https://github.com/bonomat/rust-lightning-p2p-derivatives", rev = "e49030e" } -rust-bitcoin-coin-selection = { git = "https://github.com/p2pderivatives/rust-bitcoin-coin-selection" } - -esplora-client = { git = "https://github.com/bitcoindevkit/rust-esplora-client", rev = "269360f" } +rust-bitcoin-coin-selection = { git = "https://github.com/p2pderivatives/rust-bitcoin-coin-selection", rev = "4054519" } +esplora-client = { git = "https://github.com/get10101/rust-esplora-client", rev = "24508f7" } [profile.test.package.proptest] opt-level = 3 diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index c2bc52ced..186dc71fe 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -49,7 +49,7 @@ Note: 10101 app requires all the other services (e.g. Docker setup, coordinator, ### Run the coordinator In order to successfully run the coordinator you will have to provide the coordinator with a PostgreSQL database. -The easiest way to do so is by starting the [local regtest dev environemnt](#development-environment) through `docker-compose up --build`. The `--build` ensures that all tables exist for `maker` and `coordinator`. +The easiest way to do so is by starting the [local regtest dev environemnt](#development-environment) through `docker compose up --build`. The `--build` ensures that all tables exist for `maker` and `coordinator`. `bash just coordinator` @@ -65,7 +65,7 @@ just c To run the coordinator you will need a PostgeSQL database. -The easiest way to do so is by starting the [local regtest dev environemnt](#development-environment) through `docker-compose up --build`. The `--build` ensures that all tables exist for `maker` and `coordinator`. +The easiest way to do so is by starting the [local regtest dev environemnt](#development-environment) through `docker compose up --build`. The `--build` ensures that all tables exist for `maker` and `coordinator`. ```bash just maker @@ -79,7 +79,7 @@ For more information on what containers are available please have a look at the To start the development environment you can just run: ```bash -docker-compose up +docker compose up ``` You can add `-d` to run the environment in the background. diff --git a/coordinator/readme.md b/coordinator/readme.md index abd308b96..757feecf8 100644 --- a/coordinator/readme.md +++ b/coordinator/readme.md @@ -29,7 +29,7 @@ cargo install diesel_cli --no-default-features --features postgres,sqlite Run this from the project root to start the database ```bash -docker-compose up -d db +docker compose up -d db ``` ### Setup diesel diff --git a/coordinator/src/bin/coordinator.rs b/coordinator/src/bin/coordinator.rs index 7f79df974..7fcefac6a 100644 --- a/coordinator/src/bin/coordinator.rs +++ b/coordinator/src/bin/coordinator.rs @@ -119,27 +119,30 @@ async fn main() -> Result<()> { data_dir.join("wallet"), )?; - let node = Arc::new(ln_dlc_node::node::Node::new( - ln_dlc_node::config::coordinator_config(), - NODE_ALIAS, - network, - data_dir.as_path(), - storage, - node_storage, - wallet_storage, - address, - SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), address.port()), - opts.electrs.clone(), - seed, - ephemeral_randomness, - settings.ln_dlc.clone(), - opts.get_oracle_infos() - .into_iter() - .map(|o| o.into()) - .collect(), - XOnlyPublicKey::from_str(&opts.oracle_pubkey).expect("valid public key"), - node_event_handler.clone(), - )?); + let node = Arc::new( + ln_dlc_node::node::Node::new( + ln_dlc_node::config::coordinator_config(), + NODE_ALIAS, + network, + data_dir.as_path(), + storage, + node_storage, + wallet_storage, + address, + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), address.port()), + opts.electrs.clone(), + seed, + ephemeral_randomness, + settings.ln_dlc.clone(), + opts.get_oracle_infos() + .into_iter() + .map(|o| o.into()) + .collect(), + XOnlyPublicKey::from_str(&opts.oracle_pubkey).expect("valid public key"), + node_event_handler.clone(), + ) + .await?, + ); let dlc_handler = DlcHandler::new(pool.clone(), node.clone()); let _handle = dlc_handler::spawn_handling_outbound_dlc_messages( diff --git a/coordinator/src/collaborative_revert.rs b/coordinator/src/collaborative_revert.rs index 6b962b2aa..c481d0f43 100644 --- a/coordinator/src/collaborative_revert.rs +++ b/coordinator/src/collaborative_revert.rs @@ -22,6 +22,7 @@ use dlc_manager::channel::ClosedChannel; use dlc_manager::DlcChannelId; use dlc_manager::Signer; use dlc_manager::Storage; +use futures::executor::block_on; use ln_dlc_node::bitcoin_conversion::to_ecdsa_signature_29; use ln_dlc_node::bitcoin_conversion::to_secp_pk_30; use ln_dlc_node::bitcoin_conversion::to_tx_29; @@ -227,8 +228,7 @@ pub fn confirm_collaborative_revert( "Broadcasting collaborative revert transaction" ); - node.blockchain - .broadcast_transaction_blocking(&revert_transaction) + block_on(node.blockchain.broadcast_transaction(&revert_transaction)) .context("Could not broadcast transaction")?; // TODO: We should probably not modify the state until the transaction has been confirmed. diff --git a/crates/ln-dlc-node/Cargo.toml b/crates/ln-dlc-node/Cargo.toml index 2bbdee7fb..b1a0d8173 100644 --- a/crates/ln-dlc-node/Cargo.toml +++ b/crates/ln-dlc-node/Cargo.toml @@ -8,10 +8,9 @@ description = "A common interface for using Lightning and DLC channels side-by-s [dependencies] anyhow = { version = "1", features = ["backtrace"] } -async-trait = "0.1.71" bdk = { version = "1.0.0-alpha.6", features = ["std"] } bdk_coin_select = "0.2.0" -bdk_esplora = { version = "0.8.0" } +bdk_esplora = { version = "0.8.0", default-features = false, features = ["async", "async-https"] } bip39 = { version = "2", features = ["rand_core"] } bitcoin = { version = "0.30" } bitcoin_old = { package = "bitcoin", version = "0.29.2" } @@ -27,7 +26,7 @@ lightning = { version = "0.0.117", features = ["max_level_trace", "std"] } lightning-background-processor = { version = "0.0.117", features = ["futures"] } lightning-invoice = { version = "0.25" } lightning-persister = { version = "0.0.117" } -lightning-transaction-sync = { version = "0.0.117", features = ["esplora-blocking"] } +lightning-transaction-sync = { version = "0.0.117", features = ["esplora-async-https"] } ln-dlc-storage = { path = "../../crates/ln-dlc-storage" } log = "0.4.17" mempool = { path = "../../crates/mempool" } @@ -44,12 +43,13 @@ sha2 = "0.10" thiserror = "1" time = "0.3" tokio = { version = "1", default-features = false, features = ["io-util", "macros", "rt", "rt-multi-thread", "sync", "time", "tracing"] } +tokio_with_wasm = "0.4.3" tracing = "0.1.37" tracing-log = "0.1.3" -ureq = "2.5.0" uuid = { version = "1.3.0", features = ["v4", "serde"] } axum = { version = "0.6", features = ["ws"], optional = true } +serde_json = "1.0.114" tokio-tungstenite-wasm = { version = "0.3.0", features = ["native-tls"], optional = true } # To enable JS support when compiling under wasm diff --git a/crates/ln-dlc-node/src/blockchain.rs b/crates/ln-dlc-node/src/blockchain.rs index 282cb9a81..a23b84fb1 100644 --- a/crates/ln-dlc-node/src/blockchain.rs +++ b/crates/ln-dlc-node/src/blockchain.rs @@ -11,6 +11,7 @@ use bitcoin::BlockHash; use bitcoin::OutPoint; use bitcoin::Transaction; use bitcoin::Txid; +use futures::executor::block_on; use std::sync::Arc; use tokio::task::spawn_blocking; use tracing::instrument; @@ -20,91 +21,69 @@ const SOCKET_TIMEOUT: u64 = 30; #[derive(Clone)] pub struct Blockchain { /// Async client used during on-chain syncing and, sometimes, to broadcast transactions. - pub(crate) esplora_client_async: esplora_client::AsyncClient, - /// Blocking client used when the task to be performed is in a blocking context (usually - /// blocking trait methods). - esplora_client_blocking: esplora_client::BlockingClient, + pub(crate) esplora_client: esplora_client::AsyncClient, node_storage: Arc, } impl Blockchain where - N: Storage, + N: Storage + Send + Sync, { pub fn new(electrs_url: String, node_storage: Arc) -> Result { let esplora_client_async = esplora_client::Builder::new(&electrs_url) .timeout(SOCKET_TIMEOUT) .build_async()?; - let esplora_client_blocking = esplora_client::Builder::new(&electrs_url) - .timeout(SOCKET_TIMEOUT) - .build_blocking()?; Ok(Self { - esplora_client_async, - esplora_client_blocking, + esplora_client: esplora_client_async, node_storage, }) } - #[instrument(skip_all, fields(txid = %tx.txid()))] - pub fn broadcast_transaction_blocking(&self, tx: &Transaction) -> Result { - let txid = tx.txid(); - - tracing::info!(raw_tx = %serialize_hex(&tx), "Broadcasting transaction"); - - if let Err(e) = self.node_storage.upsert_transaction(tx.into()) { - tracing::error!("Failed to store transaction. Error: {e:#}"); - } - - self.esplora_client_blocking - .broadcast(tx) - .with_context(|| format!("Failed to broadcast transaction {txid}"))?; - - Ok(txid) - } - - pub fn get_blockchain_tip(&self) -> Result { - let height = self.esplora_client_blocking.get_height()?; + pub async fn get_blockchain_tip(&self) -> Result { + let height = self.esplora_client.get_height().await?; Ok(height as u64) } - pub fn get_block_hash(&self, height: u64) -> Result { - let block_hash = self.esplora_client_blocking.get_block_hash(height as u32)?; + pub async fn get_block_hash(&self, height: u64) -> Result { + let block_hash = self.esplora_client.get_block_hash(height as u32).await?; Ok(block_hash) } - pub fn get_block_by_hash(&self, block_hash: &BlockHash) -> Result { + pub async fn get_block_by_hash(&self, block_hash: &BlockHash) -> Result { let block = self - .esplora_client_blocking - .get_block_by_hash(block_hash)? + .esplora_client + .get_block_by_hash(block_hash) + .await? .context("Could not find block")?; Ok(block) } - pub fn get_transaction(&self, txid: &Txid) -> Result> { - let tx = self.esplora_client_blocking.get_tx(txid)?; + pub async fn get_transaction(&self, txid: &Txid) -> Result> { + let tx = self.esplora_client.get_tx(txid).await?; Ok(tx) } - pub fn get_transaction_confirmations(&self, txid: &Txid) -> Result { - let status = self.esplora_client_blocking.get_tx_status(txid)?; + pub async fn get_transaction_confirmations(&self, txid: &Txid) -> Result { + let status = self.esplora_client.get_tx_status(txid).await?; let tx_height = match status.block_height { Some(height) => height, None => return Ok(0), }; - self.tx_height_to_confirmations(tx_height) + self.tx_height_to_confirmations(tx_height).await } - pub fn get_txo_confirmations(&self, txo: &OutPoint) -> Result> { + pub async fn get_txo_confirmations(&self, txo: &OutPoint) -> Result> { let status = self - .esplora_client_blocking - .get_output_status(&txo.txid, txo.vout as u64)?; + .esplora_client + .get_output_status(&txo.txid, txo.vout as u64) + .await?; let (tx_height, txid) = match status { Some(OutputStatus { @@ -119,13 +98,13 @@ where _ => return Ok(None), }; - let confirmations = self.tx_height_to_confirmations(tx_height)?; + let confirmations = self.tx_height_to_confirmations(tx_height).await?; Ok(Some((confirmations, txid))) } - fn tx_height_to_confirmations(&self, tx_height: u32) -> Result { - let tip = self.esplora_client_blocking.get_height()?; + async fn tx_height_to_confirmations(&self, tx_height: u32) -> Result { + let tip = self.esplora_client.get_height().await?; let confirmations = match tip.checked_sub(tx_height) { Some(diff) => diff + 1, @@ -162,7 +141,7 @@ where tracing::error!("Failed to store transaction. Error: {e:#}"); } - self.esplora_client_async + self.esplora_client .broadcast(tx) .await .with_context(|| format!("Failed to broadcast transaction {txid}"))?; @@ -173,13 +152,13 @@ where impl lightning::chain::chaininterface::BroadcasterInterface for Blockchain where - N: Storage, + N: Storage + Send + Sync + 'static, { fn broadcast_transactions(&self, txs: &[&bitcoin_old::Transaction]) { for tx in txs { let tx = to_tx_30((*tx).clone()); - if let Err(e) = self.broadcast_transaction_blocking(&tx) { + if let Err(e) = block_on(self.broadcast_transaction(&tx)) { tracing::error!(tx = %tx.txid(), "{e:#}"); } } diff --git a/crates/ln-dlc-node/src/dlc_message.rs b/crates/ln-dlc-node/src/dlc_message.rs index 43065dc11..0f4ed35ff 100644 --- a/crates/ln-dlc-node/src/dlc_message.rs +++ b/crates/ln-dlc-node/src/dlc_message.rs @@ -6,7 +6,6 @@ use sha2::digest::FixedOutput; use sha2::Digest; use sha2::Sha256; use time::OffsetDateTime; -use ureq::serde_json; #[derive(Clone)] pub struct DlcMessage { diff --git a/crates/ln-dlc-node/src/dlc_wallet.rs b/crates/ln-dlc-node/src/dlc_wallet.rs index 3cd976510..68627cf9e 100644 --- a/crates/ln-dlc-node/src/dlc_wallet.rs +++ b/crates/ln-dlc-node/src/dlc_wallet.rs @@ -28,6 +28,7 @@ use bdk_coin_select::Target; use bitcoin::secp256k1::KeyPair; use bitcoin::Network; use bitcoin::TxIn; +use futures::executor::block_on; use ln_dlc_storage::DlcStorageProvider; use ln_dlc_storage::WalletStorage; use std::sync::Arc; @@ -58,7 +59,7 @@ impl DlcWallet { impl dlc_manager::Blockchain for DlcWallet where D: BdkStorage, - N: Storage, + N: Storage + Send + Sync + 'static, { fn send_transaction( &self, @@ -66,8 +67,7 @@ where ) -> Result<(), dlc_manager::error::Error> { let tx = to_tx_30(tx.clone()); - self.blockchain - .broadcast_transaction_blocking(&tx) + block_on(self.blockchain.broadcast_transaction(&tx)) .map_err(|e| dlc_manager::error::Error::WalletError(format!("{e:#}").into()))?; Ok(()) @@ -100,21 +100,18 @@ where &self, height: u64, ) -> Result { - let block_hash = self.blockchain.get_block_hash(height).map_err(|e| { + let block_hash = block_on(self.blockchain.get_block_hash(height)).map_err(|e| { dlc_manager::error::Error::BlockchainError(format!( "Could not find block hash at height {height}: {e:#}" )) })?; - let block = self - .blockchain - .get_block_by_hash(&block_hash) - .map_err(|e| { - dlc_manager::error::Error::BlockchainError(format!( - "Could not find block by hash {}: {e:#}", - block_hash - )) - })?; + let block = block_on(self.blockchain.get_block_by_hash(&block_hash)).map_err(|e| { + dlc_manager::error::Error::BlockchainError(format!( + "Could not find block by hash {}: {e:#}", + block_hash + )) + })?; Ok(to_block_29(block)) } @@ -125,9 +122,7 @@ where ) -> Result { let txid = to_txid_30(*txid); - let tx = self - .blockchain - .get_transaction(&txid) + let tx = block_on(self.blockchain.get_transaction(&txid)) .map_err(|e| { dlc_manager::error::Error::BlockchainError(format!( "Could not get transaction {txid}: {e:#}" @@ -148,9 +143,7 @@ where ) -> Result { let txid = to_txid_30(*txid); - let confirmations = self - .blockchain - .get_transaction_confirmations(&txid) + let confirmations = block_on(self.blockchain.get_transaction_confirmations(&txid)) .map_err(|e| { dlc_manager::error::Error::BlockchainError(format!( "Could not get confirmations for transaction {txid}: {e:#}", @@ -166,7 +159,7 @@ where ) -> Result, dlc_manager::error::Error> { let txo = to_outpoint_30(*txo); - let confirmations = self.blockchain.get_txo_confirmations(&txo).map_err(|e| { + let confirmations = block_on(self.blockchain.get_txo_confirmations(&txo)).map_err(|e| { dlc_manager::error::Error::BlockchainError(format!( "Could not get confirmations for txo {txo}: {e:#}", )) diff --git a/crates/ln-dlc-node/src/lib.rs b/crates/ln-dlc-node/src/lib.rs index 493242070..0fbe8300b 100644 --- a/crates/ln-dlc-node/src/lib.rs +++ b/crates/ln-dlc-node/src/lib.rs @@ -48,6 +48,7 @@ pub use ln::EventSender; pub use on_chain_wallet::ConfirmationStatus; pub use on_chain_wallet::EstimateFeeError; pub use on_chain_wallet::TransactionDetails; +pub use tokio_with_wasm::tokio::spawn; #[cfg(test)] mod tests; diff --git a/crates/ln-dlc-node/src/ln/app_event_handler.rs b/crates/ln-dlc-node/src/ln/app_event_handler.rs index a9ad41481..ecad8d1d1 100644 --- a/crates/ln-dlc-node/src/ln/app_event_handler.rs +++ b/crates/ln-dlc-node/src/ln/app_event_handler.rs @@ -7,24 +7,24 @@ use crate::storage::TenTenOneStorage; use crate::EventHandlerTrait; use anyhow::bail; use anyhow::Result; -use async_trait::async_trait; use lightning::events::Event; use std::sync::Arc; /// Event handler for the mobile 10101 app. // TODO: Move it out of this crate -pub struct AppEventHandler { +pub struct AppEventHandler { pub(crate) node: Arc>, pub(crate) event_sender: Option, } -impl AppEventHandler { +impl + AppEventHandler +{ pub fn new(node: Arc>, event_sender: Option) -> Self { Self { node, event_sender } } } -#[async_trait] impl EventHandlerTrait for AppEventHandler { @@ -36,7 +36,7 @@ impl { // TODO(holzeis): Update shadow channel to store the commitment transaction closing // the channel. - common_handlers::handle_spendable_outputs(&self.node, outputs)?; + common_handlers::handle_spendable_outputs(&self.node, outputs).await?; } _ => { bail!("Unhandled event"); diff --git a/crates/ln-dlc-node/src/ln/common_handlers.rs b/crates/ln-dlc-node/src/ln/common_handlers.rs index 9db0d1890..9c297c4d4 100644 --- a/crates/ln-dlc-node/src/ln/common_handlers.rs +++ b/crates/ln-dlc-node/src/ln/common_handlers.rs @@ -10,11 +10,15 @@ use lightning::chain::chaininterface::FeeEstimator; use lightning::sign::SpendableOutputDescriptor; use secp256k1_zkp::Secp256k1; use std::sync::Arc; +use tokio::task::spawn_blocking; -pub fn handle_spendable_outputs( +pub async fn handle_spendable_outputs( node: &Arc>, outputs: Vec, -) -> Result<()> { +) -> Result<()> +where + N: Send + Sync + 'static, +{ let ldk_outputs = outputs .iter() .filter(|output| { @@ -26,10 +30,9 @@ pub fn handle_spendable_outputs( return Ok(()); } for spendable_output in ldk_outputs.iter() { - if let Err(e) = node - .node_storage - .insert_spendable_output((*spendable_output).clone()) - { + let out = (*spendable_output).clone(); + let storage = node.node_storage.clone(); + if let Err(e) = spawn_blocking(move || storage.insert_spendable_output(out)).await { tracing::error!("Failed to persist spendable output: {e:#}") } } @@ -46,7 +49,8 @@ pub fn handle_spendable_outputs( )?; node.blockchain - .broadcast_transaction_blocking(&to_tx_30(spending_tx))?; + .broadcast_transaction(&to_tx_30(spending_tx)) + .await?; Ok(()) } diff --git a/crates/ln-dlc-node/src/ln/coordinator_event_handler.rs b/crates/ln-dlc-node/src/ln/coordinator_event_handler.rs index 355831030..90a613a95 100644 --- a/crates/ln-dlc-node/src/ln/coordinator_event_handler.rs +++ b/crates/ln-dlc-node/src/ln/coordinator_event_handler.rs @@ -7,24 +7,28 @@ use crate::storage::TenTenOneStorage; use crate::EventHandlerTrait; use anyhow::bail; use anyhow::Result; -use async_trait::async_trait; use lightning::events::Event; use std::sync::Arc; /// Event handler for the coordinator node. // TODO: Move it out of this crate -pub struct CoordinatorEventHandler { +pub struct CoordinatorEventHandler< + D: BdkStorage, + S: TenTenOneStorage, + N: Storage + Sync + Send + 'static, +> { pub(crate) node: Arc>, pub(crate) event_sender: Option, } -impl CoordinatorEventHandler { +impl + CoordinatorEventHandler +{ pub fn new(node: Arc>, event_sender: Option) -> Self { Self { node, event_sender } } } -#[async_trait] impl EventHandlerTrait for CoordinatorEventHandler { @@ -40,7 +44,7 @@ impl { // TODO(holzeis): Update shadow channel to store the commitment transaction closing // the channel. - common_handlers::handle_spendable_outputs(&self.node, outputs)?; + common_handlers::handle_spendable_outputs(&self.node, outputs).await?; } _ => { bail!("Unhandled event"); diff --git a/crates/ln-dlc-node/src/ln/event_handler.rs b/crates/ln-dlc-node/src/ln/event_handler.rs index cd1671845..5b04e03f8 100644 --- a/crates/ln-dlc-node/src/ln/event_handler.rs +++ b/crates/ln-dlc-node/src/ln/event_handler.rs @@ -1,29 +1,46 @@ use anyhow::Result; -use async_trait::async_trait; use lightning::events::Event; +use std::future::Future; use std::sync::Arc; use tokio::sync::watch; pub type EventSender = watch::Sender>; -#[async_trait] +// Under non-WASM, we spawn tasks using tokio. Therefore, they must be Send + Sync +#[cfg(not(target_arch = "wasm32"))] +pub trait EventHandlerFuture: Future + Send + Sync {} + +#[cfg(not(target_arch = "wasm32"))] +impl EventHandlerFuture for F where F: Future + Send + Sync {} + +// Under WASM, we spawn tasks using wasm_bindgen_futures, so Send + Sync is not required. +// Additionally, they _cannot_ be Send + Sync, as the esplora-client futures are not Send + Sync +// since they bind to JavaScript promises (which are not Send + Sync) +#[cfg(target_arch = "wasm32")] +pub trait EventHandlerFuture: Future {} + +#[cfg(target_arch = "wasm32")] +impl EventHandlerFuture for F where F: Future {} + pub trait EventHandlerTrait: Send + Sync { - async fn match_event(&self, event: Event) -> Result<()>; + fn match_event(&self, event: Event) -> impl EventHandlerFuture>; - async fn handle_event(&self, event: Event) { - tracing::debug!(?event, "Received event"); + fn handle_event(&self, event: Event) -> impl EventHandlerFuture<()> { + async move { + tracing::debug!(?event, "Received event"); - let event_str = format!("{event:?}"); + let event_str = format!("{event:?}"); - match self.match_event(event.clone()).await { - Ok(()) => tracing::debug!(event = ?event_str, "Successfully handled event"), - Err(e) => tracing::error!("Failed to handle event. Error: {e:#}"), - } + match self.match_event(event.clone()).await { + Ok(()) => tracing::debug!(event = ?event_str, "Successfully handled event"), + Err(e) => tracing::error!("Failed to handle event. Error: {e:#}"), + } - if let Some(event_sender) = self.event_sender() { - match event_sender.send(Some(event)) { - Ok(()) => tracing::trace!("Sent event to subscriber"), - Err(e) => tracing::error!("Failed to send event to subscriber: {e:#}"), + if let Some(event_sender) = self.event_sender() { + match event_sender.send(Some(event)) { + Ok(()) => tracing::trace!("Sent event to subscriber"), + Err(e) => tracing::error!("Failed to send event to subscriber: {e:#}"), + } } } } @@ -34,7 +51,6 @@ pub trait EventHandlerTrait: Send + Sync { } pub mod handlers {} -#[async_trait] impl EventHandlerTrait for Arc { async fn match_event(&self, event: Event) -> Result<()> { (**self).match_event(event).await diff --git a/crates/ln-dlc-node/src/ln/manage_spendable_outputs.rs b/crates/ln-dlc-node/src/ln/manage_spendable_outputs.rs index 3d499cfcc..5188b50f5 100644 --- a/crates/ln-dlc-node/src/ln/manage_spendable_outputs.rs +++ b/crates/ln-dlc-node/src/ln/manage_spendable_outputs.rs @@ -22,6 +22,7 @@ use lightning::sign::StaticPaymentOutputDescriptor; use secp256k1_zkp::Secp256k1; use std::borrow::Borrow; use std::sync::Arc; +use tokio::task::spawn_blocking; /// Number of confirmations required to consider an LDK spendable output _spent_. /// @@ -29,19 +30,23 @@ use std::sync::Arc; const REQUIRED_CONFIRMATIONS: u32 = 6; /// Determine what to do with a [`SpendableOutputDescriptor`] and do it. -pub fn manage_spendable_outputs( +pub async fn manage_spendable_outputs( node_storage: Arc, - esplora_client: impl Borrow, + esplora_client: impl Borrow, wallet: impl Borrow>, blockchain: impl Borrow>, fee_rate_estimator: impl Borrow, keys_manager: impl Borrow>, -) -> Result<()> { +) -> Result<()> +where + N: Send + Sync + 'static, +{ let mut outputs_to_spend = Vec::new(); - let spendable_outputs = &node_storage.all_spendable_outputs()?; + let storage = node_storage.clone(); + let spendable_outputs = &(spawn_blocking(move || storage.all_spendable_outputs()).await??); for output in spendable_outputs.iter() { - let action = match choose_spendable_output_action(esplora_client.borrow(), output) { + let action = match choose_spendable_output_action(esplora_client.borrow(), output).await { Ok(action) => action, Err(e) => { tracing::error!( @@ -85,7 +90,8 @@ pub fn manage_spendable_outputs( blockchain .borrow() - .broadcast_transaction_blocking(&to_tx_30(spending_tx))?; + .broadcast_transaction(&to_tx_30(spending_tx)) + .await?; Ok(()) } @@ -98,8 +104,8 @@ enum Action { /// Decide on which [`Action`] should be performed based on the characteristics and status of a /// [`SpendableOutputDescriptor`]. -fn choose_spendable_output_action( - esplora_client: &esplora_client::BlockingClient, +async fn choose_spendable_output_action( + esplora_client: &esplora_client::AsyncClient, output: &SpendableOutputDescriptor, ) -> Result { use SpendableOutputDescriptor::*; @@ -112,6 +118,7 @@ fn choose_spendable_output_action( let output_status = esplora_client .get_output_status(&to_txid_30(outpoint.txid), outpoint.index.into()) + .await .context("Could not get spendable output status")?; match output_status { @@ -128,7 +135,7 @@ fn choose_spendable_output_action( }), .. }) => { - let current_height = esplora_client.get_height()?; + let current_height = esplora_client.get_height().await?; let confirmations = current_height .checked_sub(confirmation_height) diff --git a/crates/ln-dlc-node/src/networking/tcp.rs b/crates/ln-dlc-node/src/networking/tcp.rs index adfae866f..86b29c690 100644 --- a/crates/ln-dlc-node/src/networking/tcp.rs +++ b/crates/ln-dlc-node/src/networking/tcp.rs @@ -196,7 +196,7 @@ impl Connection { { // Create a waker to wake up poll_event_process, above let (event_waker, event_receiver) = mpsc::channel(1); - tokio::spawn(Self::poll_event_process( + crate::spawn(Self::poll_event_process( peer_manager.clone(), event_receiver, )); @@ -368,7 +368,7 @@ where .new_inbound_connection(descriptor, remote_addr) .is_ok() { - Some(tokio::spawn(Connection::schedule_read( + Some(crate::spawn(Connection::schedule_read( peer_manager, us, reader, @@ -423,7 +423,7 @@ where descriptor, remote_addr, ) { - Some(tokio::spawn(async move { + Some(crate::spawn(async move { // We should essentially always have enough room in a TCP socket buffer to send the // initial 10s of bytes. However, tokio running in single-threaded mode will always // fail writes and wake us back up later to write. Thus, we handle a single diff --git a/crates/ln-dlc-node/src/node/channel_manager.rs b/crates/ln-dlc-node/src/node/channel_manager.rs index 597bfdcbe..7fd22049a 100644 --- a/crates/ln-dlc-node/src/node/channel_manager.rs +++ b/crates/ln-dlc-node/src/node/channel_manager.rs @@ -39,7 +39,11 @@ pub type ChannelManager = lightning::ln::channelmanager::ChannelManager >; #[allow(clippy::too_many_arguments)] -pub(crate) fn build( +pub(crate) async fn build< + D: BdkStorage, + S: TenTenOneStorage, + N: Storage + Send + Sync + 'static, +>( keys_manager: Arc>, blockchain: Arc>, fee_rate_estimator: Arc, @@ -65,8 +69,8 @@ pub(crate) fn build( tracing::info!("Did not find channel manager data. {e:#}"); tracing::info!("Initializing new channel manager"); - let height = blockchain.get_blockchain_tip()?; - let block_hash = blockchain.get_block_hash(height)?; + let height = blockchain.get_blockchain_tip().await?; + let block_hash = blockchain.get_block_hash(height).await?; return Ok(ChannelManager::new( fee_rate_estimator, diff --git a/crates/ln-dlc-node/src/node/dlc_channel.rs b/crates/ln-dlc-node/src/node/dlc_channel.rs index a2eea0ef9..598c13a9e 100644 --- a/crates/ln-dlc-node/src/node/dlc_channel.rs +++ b/crates/ln-dlc-node/src/node/dlc_channel.rs @@ -59,6 +59,7 @@ impl { + // TODO(wasm): sync due to dlc_manager spawn_blocking({ let dlc_manager = self.dlc_manager.clone(); let event_handler = self.event_handler.clone(); @@ -212,6 +214,7 @@ impl Result { tracing::info!(channel_id = %hex::encode(dlc_channel_id), "Proposing a DLC channel update"); + // TODO(wasm): sync due to dlc_manager spawn_blocking({ let dlc_manager = self.dlc_manager.clone(); let dlc_channel_id = *dlc_channel_id; @@ -785,7 +789,11 @@ impl( +pub fn send_dlc_message< + D: BdkStorage, + S: TenTenOneStorage + 'static, + N: LnDlcStorage + Send + Sync + 'static, +>( dlc_message_handler: &DlcMessageHandler, peer_manager: &PeerManager, node_id: PublicKey, diff --git a/crates/ln-dlc-node/src/node/dlc_manager.rs b/crates/ln-dlc-node/src/node/dlc_manager.rs index 88f2322b4..4fe76d539 100644 --- a/crates/ln-dlc-node/src/node/dlc_manager.rs +++ b/crates/ln-dlc-node/src/node/dlc_manager.rs @@ -28,7 +28,7 @@ pub type DlcManager = dlc_manager::manager::Manager< Arc, >; -pub fn build( +pub fn build( data_dir: &Path, wallet: Arc>, dlc_storage: Arc>, diff --git a/crates/ln-dlc-node/src/node/mod.rs b/crates/ln-dlc-node/src/node/mod.rs index cf46e91bf..c7dcd1bf8 100644 --- a/crates/ln-dlc-node/src/node/mod.rs +++ b/crates/ln-dlc-node/src/node/mod.rs @@ -80,6 +80,7 @@ pub mod dlc_channel; pub mod event; pub mod peer_manager; +use crate::spawn; pub use ::dlc_manager as rust_dlc_manager; pub use channel_manager::ChannelManager; pub use connection::TenTenOneOnionMessageHandler; @@ -113,7 +114,7 @@ pub struct LiquidityRequest { } /// An LN-DLC node. -pub struct Node { +pub struct Node { pub settings: Arc>, pub network: Network, @@ -212,7 +213,7 @@ impl( + spawn(manage_spendable_outputs_task::( self.electrs_server_url.clone(), self.node_storage.clone(), self.wallet.clone(), @@ -476,12 +479,13 @@ impl Result<()> { + pub async fn sync_lightning_wallet(&self) -> Result<()> { lightning_wallet_sync( &self.channel_manager, &self.chain_monitor, &self.esplora_client, ) + .await } /// Send the given `amount_sats` sats to the given unchecked, on-chain `address`. @@ -493,6 +497,7 @@ impl Result { let address = address.require_network(self.network)?; + // TODO(wasm): sync due to computation let tx = spawn_blocking({ let wallet = self.wallet.clone(); move || { @@ -504,7 +509,7 @@ impl( channel_manager: Arc>, chain_monitor: Arc>, @@ -597,7 +602,9 @@ async fn periodic_lightning_wallet_sync< esplora_client: Arc>>, ) { loop { - if let Err(e) = lightning_wallet_sync(&channel_manager, &chain_monitor, &esplora_client) { + if let Err(e) = + lightning_wallet_sync(&channel_manager, &chain_monitor, &esplora_client).await + { tracing::error!("Background sync of Lightning wallet failed: {e:#}") } @@ -609,7 +616,11 @@ async fn periodic_lightning_wallet_sync< } } -fn lightning_wallet_sync( +async fn lightning_wallet_sync< + D: BdkStorage, + S: TenTenOneStorage, + N: Storage + Sync + Send + 'static, +>( channel_manager: &ChannelManager, chain_monitor: &ChainMonitor, esplora_client: &EsploraSyncClient>, @@ -621,6 +632,7 @@ fn lightning_wallet_sync, keys_manager: Arc>, ) { - let client = Arc::new(esplora_client::BlockingClient::from_agent( - electrs_server_url, - ureq::agent(), - )); + let client = Arc::new( + esplora_client::Builder::new(&electrs_server_url) + .build_async() + .expect("Failed to create esplora client - should be impossible!"), + ); + loop { - if let Err(e) = spawn_blocking({ - let client = client.clone(); - let node_storage = node_storage.clone(); - let ln_dlc_wallet = wallet.clone(); - let blockchain = blockchain.clone(); - let fee_rate_estimator = fee_rate_estimator.clone(); - let keys_manager = keys_manager.clone(); - move || { - manage_spendable_outputs( - node_storage, - client, - ln_dlc_wallet, - blockchain, - fee_rate_estimator, - keys_manager, - ) - } - }) + let client = client.clone(); + let node_storage = node_storage.clone(); + let ln_dlc_wallet = wallet.clone(); + let blockchain = blockchain.clone(); + let fee_rate_estimator = fee_rate_estimator.clone(); + let keys_manager = keys_manager.clone(); + + // TODO(wasm): sync due to esplora + if let Err(e) = manage_spendable_outputs( + node_storage, + client, + ln_dlc_wallet, + blockchain, + fee_rate_estimator, + keys_manager, + ) .await - .expect("task to complete") { tracing::error!("Failed to deal with spendable outputs: {e:#}"); }; @@ -773,7 +784,7 @@ fn manage_sub_channels< } .remote_handle(); - tokio::spawn(fut); + spawn(fut); remote_handle } diff --git a/crates/ln-dlc-node/src/node/oracle.rs b/crates/ln-dlc-node/src/node/oracle.rs index b8615b6d6..2e455dddf 100644 --- a/crates/ln-dlc-node/src/node/oracle.rs +++ b/crates/ln-dlc-node/src/node/oracle.rs @@ -25,7 +25,7 @@ impl From for P2PDOracleClient { } } -impl Node { +impl Node { pub fn oracle_pk(&self) -> Vec { self.oracles .clone() diff --git a/crates/ln-dlc-node/src/node/sub_channel_manager.rs b/crates/ln-dlc-node/src/node/sub_channel_manager.rs index 5e8c39293..ae99a8a22 100644 --- a/crates/ln-dlc-node/src/node/sub_channel_manager.rs +++ b/crates/ln-dlc-node/src/node/sub_channel_manager.rs @@ -31,7 +31,7 @@ pub type SubChannelManager = sub_channel_manager::SubChannelManager< Arc>, >; -pub(crate) fn build( +pub(crate) fn build( channel_manager: Arc>, dlc_manager: Arc>, monitor: Arc>, diff --git a/crates/ln-dlc-node/src/node/wallet.rs b/crates/ln-dlc-node/src/node/wallet.rs index b50f7919c..ab80d6eb1 100644 --- a/crates/ln-dlc-node/src/node/wallet.rs +++ b/crates/ln-dlc-node/src/node/wallet.rs @@ -37,9 +37,10 @@ impl Nod self.wallet.get_unused_address() } - pub fn get_blockchain_height(&self) -> Result { + pub async fn get_blockchain_height(&self) -> Result { self.blockchain .get_blockchain_tip() + .await .context("Failed to get blockchain height") } @@ -76,8 +77,9 @@ impl Nod /// Sync the state of the on-chain wallet against the blockchain. pub async fn sync_on_chain_wallet(&self) -> Result<()> { - let client = &self.blockchain.esplora_client_async; + let client = &self.blockchain.esplora_client; + // TODO(wasm): sync due to computation let (local_chain, unused_revealed_script_pubkeys, unconfirmed_txids, utxos) = spawn_blocking({ let wallet = self.wallet.clone(); @@ -109,6 +111,7 @@ impl Nod ..Default::default() }; + // TODO(wasm): sync due to bdk spawn_blocking({ let wallet = self.wallet.clone(); move || { @@ -124,7 +127,7 @@ impl Nod } pub async fn full_sync(&self, stop_gap: usize) -> Result<()> { - let client = &self.blockchain.esplora_client_async; + let client = &self.blockchain.esplora_client; let (local_chain, all_script_pubkeys) = spawn_blocking({ let wallet = self.wallet.clone(); @@ -156,6 +159,7 @@ impl Nod last_active_indices, }; + // TODO(wasm): sync due to bdk spawn_blocking({ let wallet = self.wallet.clone(); move || { diff --git a/crates/ln-dlc-node/src/tests/dlc_channel.rs b/crates/ln-dlc-node/src/tests/dlc_channel.rs index 4aea9e4db..d55ee03cd 100644 --- a/crates/ln-dlc-node/src/tests/dlc_channel.rs +++ b/crates/ln-dlc-node/src/tests/dlc_channel.rs @@ -367,7 +367,7 @@ async fn start_and_fund_app( Arc>, RunningNode, ) { - let (node, running_node) = Node::start_test_app("app").unwrap(); + let (node, running_node) = Node::start_test_app("app").await.unwrap(); node.fund(amount, n_utxos).await.unwrap(); @@ -381,7 +381,7 @@ async fn start_and_fund_coordinator( Arc>, RunningNode, ) { - let (node, running_node) = Node::start_test_coordinator("coordinator").unwrap(); + let (node, running_node) = Node::start_test_coordinator("coordinator").await.unwrap(); node.fund(amount, n_utxos).await.unwrap(); diff --git a/crates/ln-dlc-node/src/tests/mod.rs b/crates/ln-dlc-node/src/tests/mod.rs index 669a15c3d..49d4110b0 100644 --- a/crates/ln-dlc-node/src/tests/mod.rs +++ b/crates/ln-dlc-node/src/tests/mod.rs @@ -53,7 +53,6 @@ use std::sync::Once; use std::time::Duration; use time::OffsetDateTime; use tokio::sync::watch; -use tokio::task::block_in_place; use uuid::Uuid; mod bitcoind; @@ -87,10 +86,9 @@ fn init_tracing() { } impl Node { - fn start_test_app(name: &str) -> Result<(Arc, RunningNode)> { - let app_event_handler = |node, event_sender| { - Arc::new(AppEventHandler::new(node, event_sender)) as Arc - }; + async fn start_test_app(name: &str) -> Result<(Arc, RunningNode)> { + let app_event_handler = + |node, event_sender| Arc::new(AppEventHandler::new(node, event_sender)); Self::start_test( app_event_handler, @@ -105,26 +103,27 @@ impl Node Result<(Arc, RunningNode)> { + async fn start_test_coordinator(name: &str) -> Result<(Arc, RunningNode)> { Self::start_test_coordinator_internal( name, Arc::new(InMemoryStore::default()), ln_dlc_node_settings_coordinator(), None, ) + .await } - fn start_test_coordinator_internal( + async fn start_test_coordinator_internal( name: &str, storage: Arc, settings: LnDlcNodeSettings, ldk_event_sender: Option>>, ) -> Result<(Arc, RunningNode)> { - let coordinator_event_handler = |node, event_sender| { - Arc::new(CoordinatorEventHandler::new(node, event_sender)) as Arc - }; + let coordinator_event_handler = + |node, event_sender| Arc::new(CoordinatorEventHandler::new(node, event_sender)); Self::start_test( coordinator_event_handler, @@ -139,11 +138,12 @@ impl Node( - event_handler_factory: EH, + async fn start_test( + event_handler_factory: EHF, name: &str, ldk_config: UserConfig, electrs_origin: String, @@ -153,10 +153,11 @@ impl Node>>, ) -> Result<(Arc, RunningNode)> where - EH: Fn( + EH: EventHandlerTrait + 'static, + EHF: Fn( Arc>, Option, - ) -> Arc, + ) -> Arc, { let data_dir = random_tmp_dir().join(name); @@ -191,10 +192,11 @@ impl Node Result<()> { self.sync_on_chain_wallet().await?; - - block_in_place(|| { - self.sync_lightning_wallet()?; - - Ok(()) - }) + self.sync_lightning_wallet().await?; + Ok(()) } async fn fund(&self, amount: Amount, n_utxos: u64) -> Result<()> { diff --git a/justfile b/justfile index 992f53a61..1095d5f8b 100644 --- a/justfile +++ b/justfile @@ -187,7 +187,7 @@ wipe: wipe-docker wipe-coordinator wipe-maker wipe-app wipe-webapp wipe-docker: #!/usr/bin/env bash set -euxo pipefail - docker-compose down -v + docker compose down -v wipe-coordinator: pkill -9 coordinator && echo "stopped coordinator" || echo "coordinator not running, skipped" @@ -326,7 +326,7 @@ ln-dlc-node-test args="": docker # Runs background Docker services docker: #!/usr/bin/env bash - docker-compose up -d + docker compose up -d height=$(docker exec bitcoin bitcoin-cli --regtest -rpcuser=admin1 -rpcpassword=123 getblockcount) height="${height%%[[:cntrl:]]}" @@ -338,7 +338,7 @@ docker: fi docker-logs: - docker-compose logs + docker compose logs # Starts coordinator process in the background, piping logs to a file (used in other recipes) run-coordinator-detached: diff --git a/mobile/native/src/ln_dlc/mod.rs b/mobile/native/src/ln_dlc/mod.rs index 280cb34c6..f5c1030c7 100644 --- a/mobile/native/src/ln_dlc/mod.rs +++ b/mobile/native/src/ln_dlc/mod.rs @@ -306,7 +306,8 @@ pub fn run(runtime: &Runtime) -> Result<()> { vec![config::get_oracle_info().into()], config::get_oracle_info().public_key, node_event_handler.clone(), - )?; + ) + .await?; let node = Arc::new(node); let event_handler = AppEventHandler::new(node.clone(), Some(event_sender)); diff --git a/mobile/native/src/ln_dlc/node.rs b/mobile/native/src/ln_dlc/node.rs index bc464b659..a5e6dd2c3 100644 --- a/mobile/native/src/ln_dlc/node.rs +++ b/mobile/native/src/ln_dlc/node.rs @@ -98,8 +98,8 @@ pub struct WalletHistory { } impl Node { - pub fn get_blockchain_height(&self) -> Result { - self.inner.get_blockchain_height() + pub async fn get_blockchain_height(&self) -> Result { + self.inner.get_blockchain_height().await } pub fn get_wallet_balances(&self) -> Balances {