Skip to content

Commit

Permalink
WIP: Impl Anchors
Browse files Browse the repository at this point in the history
TODO:
- Decide how to expose enforcing/non-enforcing anchors
- check reserve for enforcing variant
  • Loading branch information
tnull committed Jul 24, 2023
1 parent 03dd0e1 commit 340cdd5
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 13 deletions.
7 changes: 2 additions & 5 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,12 +548,9 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
// Initialize the ChannelManager
let mut user_config = UserConfig::default();
user_config.channel_handshake_limits.force_announced_channel_preference = false;
user_config.manually_accept_inbound_channels = true;
user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;

if !config.trusted_peers_0conf.is_empty() {
// Manually accept inbound channels if we expect 0conf channel requests, avoid
// generating the events otherwise.
user_config.manually_accept_inbound_channels = true;
}
let channel_manager = {
if let Ok(mut reader) =
kv_store.read(CHANNEL_MANAGER_PERSISTENCE_NAMESPACE, CHANNEL_MANAGER_PERSISTENCE_KEY)
Expand Down
15 changes: 10 additions & 5 deletions src/event.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
hex_utils, ChannelId, ChannelManager, Config, Error, KeysManager, NetworkGraph, UserChannelId,
Wallet,
hex_utils, BumpTransactionEventHandler, ChannelId, ChannelManager, Config, Error, KeysManager,
NetworkGraph, UserChannelId, Wallet,
};

use crate::payment_store::{
Expand Down Expand Up @@ -223,8 +223,9 @@ pub(crate) struct EventHandler<K: KVStore + Sync + Send, L: Deref>
where
L::Target: Logger,
{
wallet: Arc<Wallet<bdk::database::SqliteDatabase, L>>,
event_queue: Arc<EventQueue<K, L>>,
wallet: Arc<Wallet<bdk::database::SqliteDatabase, L>>,
bump_tx_event_handler: Arc<BumpTransactionEventHandler>,
channel_manager: Arc<ChannelManager<K>>,
network_graph: Arc<NetworkGraph>,
keys_manager: Arc<KeysManager>,
Expand All @@ -239,14 +240,16 @@ where
L::Target: Logger,
{
pub fn new(
wallet: Arc<Wallet<bdk::database::SqliteDatabase, L>>, event_queue: Arc<EventQueue<K, L>>,
event_queue: Arc<EventQueue<K, L>>, wallet: Arc<Wallet<bdk::database::SqliteDatabase, L>>,
bump_tx_event_handler: Arc<BumpTransactionEventHandler>,
channel_manager: Arc<ChannelManager<K>>, network_graph: Arc<NetworkGraph>,
keys_manager: Arc<KeysManager>, payment_store: Arc<PaymentStore<K, L>>,
runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>, logger: L, config: Arc<Config>,
) -> Self {
Self {
event_queue,
wallet,
bump_tx_event_handler,
channel_manager,
network_graph,
keys_manager,
Expand Down Expand Up @@ -760,7 +763,9 @@ where
}
LdkEvent::DiscardFunding { .. } => {}
LdkEvent::HTLCIntercepted { .. } => {}
LdkEvent::BumpTransaction(_) => {}
LdkEvent::BumpTransaction(bte) => {
self.bump_tx_event_handler.handle_event(&bte);
}
}
}
}
Expand Down
16 changes: 14 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,17 @@ use io::KVStore;
use payment_store::PaymentStore;
pub use payment_store::{PaymentDetails, PaymentDirection, PaymentStatus};
use peer_store::{PeerInfo, PeerStore};
use types::{ChainMonitor, ChannelManager, KeysManager, NetworkGraph, PeerManager, Scorer};
use types::{
BumpTransactionEventHandler, ChainMonitor, ChannelManager, KeysManager, NetworkGraph,
PeerManager, Scorer,
};
pub use types::{ChannelDetails, ChannelId, PeerDetails, UserChannelId};
use wallet::Wallet;

use logger::{log_error, log_info, log_trace, FilesystemLogger, Logger};

use lightning::chain::Confirm;
use lightning::events::bump_transaction::Wallet as LdkWallet;
use lightning::ln::channelmanager::{self, PaymentId, RecipientOnionFields, Retry};
use lightning::ln::{PaymentHash, PaymentPreimage};
use lightning::sign::EntropySource;
Expand Down Expand Up @@ -634,9 +638,17 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
}
});

let event_handler = Arc::new(EventHandler::new(
let bump_tx_event_handler = Arc::new(BumpTransactionEventHandler::new(
Arc::clone(&self.wallet),
Arc::new(LdkWallet::new(Arc::clone(&self.wallet))),
Arc::clone(&self.keys_manager),
Arc::clone(&self.logger),
));

let event_handler = Arc::new(EventHandler::new(
Arc::clone(&self.event_queue),
Arc::clone(&self.wallet),
bump_tx_event_handler,
Arc::clone(&self.channel_manager),
Arc::clone(&self.network_graph),
Arc::clone(&self.keys_manager),
Expand Down
12 changes: 12 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ impl lightning::onion_message::MessageRouter for FakeMessageRouter {
}
}

pub(crate) type BumpTransactionEventHandler =
lightning::events::bump_transaction::BumpTransactionEventHandler<
Arc<Wallet<bdk::database::SqliteDatabase, Arc<FilesystemLogger>>>,
Arc<
lightning::events::bump_transaction::Wallet<
Arc<Wallet<bdk::database::SqliteDatabase, Arc<FilesystemLogger>>>,
>,
>,
Arc<WalletKeysManager<bdk::database::SqliteDatabase, Arc<FilesystemLogger>>>,
Arc<FilesystemLogger>,
>;

/// The global identifier of a channel.
///
/// Note that this will start out to be a temporary ID until channel funding negotiation is
Expand Down
100 changes: 99 additions & 1 deletion src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use lightning::chain::chaininterface::{
BroadcasterInterface, ConfirmationTarget, FeeEstimator, FEERATE_FLOOR_SATS_PER_KW,
};

use lightning::events::bump_transaction::{Utxo, WalletSource};
use lightning::ln::msgs::{DecodeError, UnsignedGossipMessage};
use lightning::ln::script::ShutdownScript;
use lightning::sign::{
Expand All @@ -21,10 +22,13 @@ use bdk::wallet::AddressIndex;
use bdk::{FeeRate, SignOptions, SyncOptions};

use bitcoin::bech32::u5;
use bitcoin::hashes::Hash;
use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, Signing};
use bitcoin::{LockTime, PackedLockTime, Script, Transaction, TxOut, Txid};
use bitcoin::util::address::WitnessVersion;
use bitcoin::util::psbt::PartiallySignedTransaction;
use bitcoin::{LockTime, PackedLockTime, Script, Transaction, TxOut, Txid, WPubkeyHash};

use std::collections::HashMap;
use std::ops::Deref;
Expand Down Expand Up @@ -347,6 +351,100 @@ where
}
}

impl<D, L: Deref> WalletSource for Wallet<D, L>
where
D: BatchDatabase,
L::Target: Logger,
{
fn list_confirmed_utxos(&self) -> Result<Vec<Utxo>, ()> {
let locked_wallet = self.inner.lock().unwrap();
let mut utxos = Vec::new();
let txs = locked_wallet.list_transactions(true).map_err(|e| {
log_error!(self.logger, "Failed to retrieve transactions from wallet: {}", e);
})?;
let unspent = locked_wallet.list_unspent().map_err(|e| {
log_error!(self.logger, "Failed to retrieve unspent transactions from wallet: {}", e);
})?;

for u in unspent {
for t in &txs {
if u.outpoint.txid == t.txid && t.confirmation_time.is_some() {
let payload =
bitcoin::util::address::Payload::from_script(&u.txout.script_pubkey)
.map_err(|e| {
log_error!(self.logger, "Failed to retrieve script payload: {}", e);
})?;

match payload {
bitcoin::util::address::Payload::WitnessProgram { version, program } => {
if version == WitnessVersion::V0 && program.len() == 20 {
let wpkh = WPubkeyHash::from_slice(&program).map_err(|e| {
log_error!(
self.logger,
"Failed to retrieve script payload: {}",
e
);
})?;
let utxo = Utxo::new_v0_p2wpkh(u.outpoint, u.txout.value, &wpkh);
utxos.push(utxo);
} else {
log_error!(
self.logger,
"Unexpected program length: {}",
program.len()
);
}
}
_ => {
log_error!(
self.logger,
"Tried to use a non-witness script. This must never happen."
);
panic!("Tried to use a non-witness script. This must never happen.");
}
}
}
}
}

Ok(utxos)
}

fn get_change_script(&self) -> Result<Script, ()> {
let locked_wallet = self.inner.lock().unwrap();
let address_info = locked_wallet.get_address(AddressIndex::New).map_err(|e| {
log_error!(self.logger, "Failed to retrieve new address from wallet: {}", e);
})?;

Ok(address_info.address.script_pubkey())
}

fn sign_tx(&self, tx: &mut Transaction) -> Result<(), ()> {
let locked_wallet = self.inner.lock().unwrap();

let mut psbt = PartiallySignedTransaction::from_unsigned_tx(tx.clone()).map_err(|e| {
log_error!(self.logger, "Failed to create PSBT: {}", e);
})?;

match locked_wallet.sign(&mut psbt, SignOptions::default()) {
Ok(finalized) => {
if !finalized {
log_error!(self.logger, "Failed to finalize PSBT.");
return Err(());
}
}
Err(err) => {
log_error!(self.logger, "Failed to sign transaction: {}", err);
return Err(());
}
}

*tx = psbt.extract_tx();

Ok(())
}
}

/// Similar to [`KeysManager`], but overrides the destination and shutdown scripts so they are
/// directly spendable by the BDK wallet.
pub struct WalletKeysManager<D, L: Deref>
Expand Down

0 comments on commit 340cdd5

Please sign in to comment.