Skip to content

Commit

Permalink
Move onchain payments API to OnchainPaymentHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
tnull committed Mar 7, 2024
1 parent 9932a70 commit 431f635
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 63 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn main() {

node.start().unwrap();

let funding_address = node.new_onchain_address();
let funding_address = node.onchain_payment().new_address();

// .. fund address ..

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ class AndroidLibTest {
val nodeId2 = node2.nodeId()
println("Node Id 2: $nodeId2")

val address1 = node1.newOnchainAddress()
val address1 = node1.onchain_payment().newOnchainAddress()
println("Funding address 1: $address1")

val address2 = node2.newOnchainAddress()
val address2 = node2.onchain_payment().newOnchainAddress()
println("Funding address 2: $address2")

node1.stop()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ class LibraryTest {
val nodeId2 = node2.nodeId()
println("Node Id 2: $nodeId2")

val address1 = node1.newOnchainAddress()
val address1 = node1.onchainPayment().newAddress()
println("Funding address 1: $address1")

val address2 = node2.newOnchainAddress()
val address2 = node2.onchainPayment().newAddress()
println("Funding address 2: $address2")

val txid1 = sendToAddress(address1, 100000u)
Expand Down
16 changes: 10 additions & 6 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,7 @@ interface Node {
sequence<SocketAddress>? listening_addresses();
Bolt11PaymentHandler bolt11_payment();
SpontaneousPaymentHandler spontaneous_payment();
[Throws=NodeError]
Address new_onchain_address();
[Throws=NodeError]
Txid send_to_onchain_address([ByRef]Address address, u64 amount_msat);
[Throws=NodeError]
Txid send_all_to_onchain_address([ByRef]Address address);
OnchainPaymentHandler onchain_payment();
[Throws=NodeError]
void connect(PublicKey node_id, SocketAddress address, boolean persist);
[Throws=NodeError]
Expand Down Expand Up @@ -111,6 +106,15 @@ interface SpontaneousPaymentHandler {
void send_probes(u64 amount_msat, PublicKey node_id);
};

interface OnchainPaymentHandler {
[Throws=NodeError]
Address new_address();
[Throws=NodeError]
Txid send_to_address([ByRef]Address address, u64 amount_msat);
[Throws=NodeError]
Txid send_all_to_address([ByRef]Address address);
};

[Error]
enum NodeError {
"AlreadyRunning",
Expand Down
4 changes: 2 additions & 2 deletions bindings/python/src/ldk_node/test_ldk_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ def test_channel_full_cycle(self):
node_id_2 = node_2.node_id()
print("Node ID 2:", node_id_2)

address_1 = node_1.new_onchain_address()
address_1 = node_1.onchain_payment().new_address()
txid_1 = send_to_address(address_1, 100000)
address_2 = node_2.new_onchain_address()
address_2 = node_2.onchain_payment().new_address()
txid_2 = send_to_address(address_2, 100000)

wait_for_tx(esplora_endpoint, txid_1)
Expand Down
44 changes: 9 additions & 35 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
//!
//! node.start().unwrap();
//!
//! let funding_address = node.new_onchain_address();
//! let funding_address = node.onchain_payment().new_address();
//!
//! // .. fund address ..
//!
Expand Down Expand Up @@ -130,7 +130,7 @@ use connection::ConnectionManager;
use event::{EventHandler, EventQueue};
use gossip::GossipSource;
use liquidity::LiquiditySource;
use payment::{Bolt11PaymentHandler, SpontaneousPaymentHandler};
use payment::{Bolt11PaymentHandler, OnchainPaymentHandler, SpontaneousPaymentHandler};
use payment_store::PaymentStore;
pub use payment_store::{LSPFeeLimits, PaymentDetails, PaymentDirection, PaymentStatus};
use peer_store::{PeerInfo, PeerStore};
Expand All @@ -154,7 +154,6 @@ use lightning_background_processor::process_events_async;
use lightning_transaction_sync::EsploraSyncClient;

use bitcoin::secp256k1::PublicKey;
use bitcoin::{Address, Txid};

use rand::Rng;

Expand Down Expand Up @@ -841,38 +840,13 @@ impl Node {
))
}

/// Retrieve a new on-chain/funding address.
pub fn new_onchain_address(&self) -> Result<Address, Error> {
let funding_address = self.wallet.get_new_address()?;
log_info!(self.logger, "Generated new funding address: {}", funding_address);
Ok(funding_address)
}

/// Send an on-chain payment to the given address.
pub fn send_to_onchain_address(
&self, address: &bitcoin::Address, amount_sats: u64,
) -> Result<Txid, Error> {
let rt_lock = self.runtime.read().unwrap();
if rt_lock.is_none() {
return Err(Error::NotRunning);
}

let cur_balance = self.wallet.get_balance()?;
if cur_balance.get_spendable() < amount_sats {
log_error!(self.logger, "Unable to send payment due to insufficient funds.");
return Err(Error::InsufficientFunds);
}
self.wallet.send_to_address(address, Some(amount_sats))
}

/// Send an on-chain payment to the given address, draining all the available funds.
pub fn send_all_to_onchain_address(&self, address: &bitcoin::Address) -> Result<Txid, Error> {
let rt_lock = self.runtime.read().unwrap();
if rt_lock.is_none() {
return Err(Error::NotRunning);
}

self.wallet.send_to_address(address, None)
/// Returns a payment handler allowing to send and receive on-chain payments.
pub fn onchain_payment(&self) -> Arc<OnchainPaymentHandler> {
Arc::new(OnchainPaymentHandler::new(
Arc::clone(&self.runtime),
Arc::clone(&self.wallet),
Arc::clone(&self.logger),
))
}

/// Retrieve a list of known channels.
Expand Down
2 changes: 2 additions & 0 deletions src/payment/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! Handlers for different types of payments.
mod bolt11;
mod onchain;
mod spontaneous;

pub use bolt11::Bolt11PaymentHandler;
pub use onchain::OnchainPaymentHandler;
pub use spontaneous::SpontaneousPaymentHandler;
63 changes: 63 additions & 0 deletions src/payment/onchain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//! Holds a payment handler allowing to send and receive on-chain payments.
use crate::error::Error;
use crate::logger::{log_error, log_info, FilesystemLogger, Logger};
use crate::types::Wallet;

use bitcoin::{Address, Txid};

use std::sync::{Arc, RwLock};

/// A payment handler allowing to send and receive on-chain payments.
///
/// Should be retrieved by calling [`Node::onchain_payment`].
///
/// [`Node::onchain_payment`]: crate::Node::onchain_payment
pub struct OnchainPaymentHandler {
runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>,
wallet: Arc<Wallet>,
logger: Arc<FilesystemLogger>,
}

impl OnchainPaymentHandler {
pub(crate) fn new(
runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>, wallet: Arc<Wallet>,
logger: Arc<FilesystemLogger>,
) -> Self {
Self { runtime, wallet, logger }
}

/// Retrieve a new on-chain/funding address.
pub fn new_address(&self) -> Result<Address, Error> {
let funding_address = self.wallet.get_new_address()?;
log_info!(self.logger, "Generated new funding address: {}", funding_address);
Ok(funding_address)
}

/// Send an on-chain payment to the given address.
pub fn send_to_address(
&self, address: &bitcoin::Address, amount_sats: u64,
) -> Result<Txid, Error> {
let rt_lock = self.runtime.read().unwrap();
if rt_lock.is_none() {
return Err(Error::NotRunning);
}

let cur_balance = self.wallet.get_balance()?;
if cur_balance.get_spendable() < amount_sats {
log_error!(self.logger, "Unable to send payment due to insufficient funds.");
return Err(Error::InsufficientFunds);
}
self.wallet.send_to_address(address, Some(amount_sats))
}

/// Send an on-chain payment to the given address, draining all the available funds.
pub fn send_all_to_address(&self, address: &bitcoin::Address) -> Result<Txid, Error> {
let rt_lock = self.runtime.read().unwrap();
if rt_lock.is_none() {
return Err(Error::NotRunning);
}

self.wallet.send_to_address(address, None)
}
}
3 changes: 1 addition & 2 deletions src/uniffi_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub use lightning::util::string::UntrustedString;

pub use lightning_invoice::Bolt11Invoice;

pub use bitcoin::{BlockHash, Network, OutPoint};
pub use bitcoin::{Address, BlockHash, Network, OutPoint, Txid};

pub use bip39::Mnemonic;

Expand All @@ -17,7 +17,6 @@ use crate::{SocketAddress, UserChannelId};
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::Hash;
use bitcoin::secp256k1::PublicKey;
use bitcoin::{Address, Txid};
use lightning_invoice::SignedRawBolt11Invoice;

use std::convert::TryInto;
Expand Down
4 changes: 2 additions & 2 deletions tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,8 @@ pub fn open_channel(
pub(crate) fn do_channel_full_cycle<E: ElectrumApi>(
node_a: TestNode, node_b: TestNode, bitcoind: &BitcoindClient, electrsd: &E, allow_0conf: bool,
) {
let addr_a = node_a.new_onchain_address().unwrap();
let addr_b = node_b.new_onchain_address().unwrap();
let addr_a = node_a.onchain_payment().new_address().unwrap();
let addr_b = node_b.onchain_payment().new_address().unwrap();

let premine_amount_sat = 100_000;

Expand Down
2 changes: 1 addition & 1 deletion tests/integration_tests_cln.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ fn test_cln() {
node.start().unwrap();

// Premine some funds and distribute
let address = node.new_onchain_address().unwrap();
let address = node.onchain_payment().new_address().unwrap();
let premine_amount = Amount::from_sat(5_000_000);
common::premine_and_distribute_funds(
&bitcoind_client,
Expand Down
23 changes: 13 additions & 10 deletions tests/integration_tests_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ fn channel_open_fails_when_funds_insufficient() {
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
let (node_a, node_b) = setup_two_nodes(&electrsd, false);

let addr_a = node_a.new_onchain_address().unwrap();
let addr_b = node_b.new_onchain_address().unwrap();
let addr_a = node_a.onchain_payment().new_address().unwrap();
let addr_b = node_b.onchain_payment().new_address().unwrap();

let premine_amount_sat = 100_000;

Expand Down Expand Up @@ -79,7 +79,7 @@ fn multi_hop_sending() {
nodes.push(node);
}

let addresses = nodes.iter().map(|n| n.new_onchain_address().unwrap()).collect();
let addresses = nodes.iter().map(|n| n.onchain_payment().new_address().unwrap()).collect();
let premine_amount_sat = 5_000_000;
premine_and_distribute_funds(
&bitcoind.client,
Expand Down Expand Up @@ -169,7 +169,7 @@ fn start_stop_reinit() {
let expected_node_id = node.node_id();
assert_eq!(node.start(), Err(NodeError::AlreadyRunning));

let funding_address = node.new_onchain_address().unwrap();
let funding_address = node.onchain_payment().new_address().unwrap();

assert_eq!(node.list_balances().total_onchain_balance_sats, 0);

Expand Down Expand Up @@ -223,8 +223,8 @@ fn onchain_spend_receive() {
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
let (node_a, node_b) = setup_two_nodes(&electrsd, false);

let addr_a = node_a.new_onchain_address().unwrap();
let addr_b = node_b.new_onchain_address().unwrap();
let addr_a = node_a.onchain_payment().new_address().unwrap();
let addr_b = node_b.onchain_payment().new_address().unwrap();

premine_and_distribute_funds(
&bitcoind.client,
Expand All @@ -237,9 +237,12 @@ fn onchain_spend_receive() {
node_b.sync_wallets().unwrap();
assert_eq!(node_b.list_balances().spendable_onchain_balance_sats, 100000);

assert_eq!(Err(NodeError::InsufficientFunds), node_a.send_to_onchain_address(&addr_b, 1000));
assert_eq!(
Err(NodeError::InsufficientFunds),
node_a.onchain_payment().send_to_address(&addr_b, 1000)
);

let txid = node_b.send_to_onchain_address(&addr_a, 1000).unwrap();
let txid = node_b.onchain_payment().send_to_address(&addr_a, 1000).unwrap();
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6);
wait_for_tx(&electrsd.client, txid);

Expand All @@ -250,8 +253,8 @@ fn onchain_spend_receive() {
assert!(node_b.list_balances().spendable_onchain_balance_sats > 98000);
assert!(node_b.list_balances().spendable_onchain_balance_sats < 100000);

let addr_b = node_b.new_onchain_address().unwrap();
let txid = node_a.send_all_to_onchain_address(&addr_b).unwrap();
let addr_b = node_b.onchain_payment().new_address().unwrap();
let txid = node_a.onchain_payment().send_all_to_address(&addr_b).unwrap();
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6);
wait_for_tx(&electrsd.client, txid);

Expand Down

0 comments on commit 431f635

Please sign in to comment.