Skip to content

Commit

Permalink
feat: support compiling ln-dlc-node under wasm
Browse files Browse the repository at this point in the history
  • Loading branch information
Restioson committed Mar 18, 2024
1 parent e76604e commit dd67a60
Show file tree
Hide file tree
Showing 29 changed files with 375 additions and 308 deletions.
198 changes: 117 additions & 81 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand All @@ -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
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion coordinator/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
45 changes: 24 additions & 21 deletions coordinator/src/bin/coordinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
4 changes: 2 additions & 2 deletions coordinator/src/collaborative_revert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions crates/ln-dlc-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand All @@ -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" }
Expand All @@ -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
Expand Down
75 changes: 27 additions & 48 deletions crates/ln-dlc-node/src/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,91 +21,69 @@ const SOCKET_TIMEOUT: u64 = 30;
#[derive(Clone)]
pub struct Blockchain<N> {
/// 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<N>,
}

impl<N> Blockchain<N>
where
N: Storage,
N: Storage + Send + Sync,
{
pub fn new(electrs_url: String, node_storage: Arc<N>) -> Result<Self> {
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<Txid> {
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<u64> {
let height = self.esplora_client_blocking.get_height()?;
pub async fn get_blockchain_tip(&self) -> Result<u64> {
let height = self.esplora_client.get_height().await?;

Ok(height as u64)
}

pub fn get_block_hash(&self, height: u64) -> Result<BlockHash> {
let block_hash = self.esplora_client_blocking.get_block_hash(height as u32)?;
pub async fn get_block_hash(&self, height: u64) -> Result<BlockHash> {
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<Block> {
pub async fn get_block_by_hash(&self, block_hash: &BlockHash) -> Result<Block> {
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<Option<Transaction>> {
let tx = self.esplora_client_blocking.get_tx(txid)?;
pub async fn get_transaction(&self, txid: &Txid) -> Result<Option<Transaction>> {
let tx = self.esplora_client.get_tx(txid).await?;

Ok(tx)
}

pub fn get_transaction_confirmations(&self, txid: &Txid) -> Result<u32> {
let status = self.esplora_client_blocking.get_tx_status(txid)?;
pub async fn get_transaction_confirmations(&self, txid: &Txid) -> Result<u32> {
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<Option<(u32, Txid)>> {
pub async fn get_txo_confirmations(&self, txo: &OutPoint) -> Result<Option<(u32, Txid)>> {
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 {
Expand All @@ -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<u32> {
let tip = self.esplora_client_blocking.get_height()?;
async fn tx_height_to_confirmations(&self, tx_height: u32) -> Result<u32> {
let tip = self.esplora_client.get_height().await?;

let confirmations = match tip.checked_sub(tx_height) {
Some(diff) => diff + 1,
Expand Down Expand Up @@ -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}"))?;
Expand All @@ -173,13 +152,13 @@ where

impl<N> lightning::chain::chaininterface::BroadcasterInterface for Blockchain<N>
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:#}");
}
}
Expand Down
1 change: 0 additions & 1 deletion crates/ln-dlc-node/src/dlc_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading

0 comments on commit dd67a60

Please sign in to comment.