Skip to content

Commit 018dd52

Browse files
committed
BaseSign + ChannelMonitor temporary error support
1 parent 716539e commit 018dd52

File tree

7 files changed

+153
-93
lines changed

7 files changed

+153
-93
lines changed

lightning/src/chain/channelmonitor.rs

+53-29
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use chain;
4242
use chain::{BestBlock, WatchedOutput};
4343
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
4444
use chain::transaction::{OutPoint, TransactionData};
45-
use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface};
45+
use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface, SignError};
4646
use chain::onchaintx::OnchainTxHandler;
4747
use chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput};
4848
use chain::Filter;
@@ -1098,7 +1098,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
10981098
broadcaster: &B,
10991099
fee_estimator: &F,
11001100
logger: &L,
1101-
) where
1101+
) -> Result<(), SignError> where
11021102
B::Target: BroadcasterInterface,
11031103
F::Target: FeeEstimator,
11041104
L::Target: Logger,
@@ -1111,7 +1111,8 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
11111111
&self,
11121112
broadcaster: &B,
11131113
logger: &L,
1114-
) where
1114+
)
1115+
where
11151116
B::Target: BroadcasterInterface,
11161117
L::Target: Logger,
11171118
{
@@ -1210,7 +1211,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
12101211
/// substantial amount of time (a month or even a year) to get back funds. Best may be to contact
12111212
/// out-of-band the other node operator to coordinate with him if option is available to you.
12121213
/// In any-case, choice is up to the user.
1213-
pub fn get_latest_holder_commitment_txn<L: Deref>(&self, logger: &L) -> Vec<Transaction>
1214+
pub fn get_latest_holder_commitment_txn<L: Deref>(&self, logger: &L) -> Result<Vec<Transaction>, SignError>
12141215
where L::Target: Logger {
12151216
self.inner.lock().unwrap().get_latest_holder_commitment_txn(logger)
12161217
}
@@ -1847,7 +1848,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18471848

18481849
/// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
18491850
/// commitment_tx_infos which contain the payment hash have been revoked.
1850-
fn provide_payment_preimage<B: Deref, F: Deref, L: Deref>(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, fee_estimator: &F, logger: &L)
1851+
fn provide_payment_preimage<B: Deref, F: Deref, L: Deref>(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, fee_estimator: &F, logger: &L) -> Result<(), SignError>
18511852
where B::Target: BroadcasterInterface,
18521853
F::Target: FeeEstimator,
18531854
L::Target: Logger,
@@ -1859,19 +1860,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18591860
macro_rules! claim_htlcs {
18601861
($commitment_number: expr, $txid: expr) => {
18611862
let htlc_claim_reqs = self.get_counterparty_htlc_output_claim_reqs($commitment_number, $txid, None);
1862-
self.onchain_tx_handler.update_claims_view(&Vec::new(), htlc_claim_reqs, self.best_block.height(), self.best_block.height(), broadcaster, fee_estimator, logger);
1863+
self.onchain_tx_handler.update_claims_view(&Vec::new(), htlc_claim_reqs, self.best_block.height(), self.best_block.height(), broadcaster, fee_estimator, logger)?;
18631864
}
18641865
}
18651866
if let Some(txid) = self.current_counterparty_commitment_txid {
18661867
if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) {
18671868
claim_htlcs!(*commitment_number, txid);
1868-
return;
1869+
return Ok(());
18691870
}
18701871
}
18711872
if let Some(txid) = self.prev_counterparty_commitment_txid {
18721873
if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) {
18731874
claim_htlcs!(*commitment_number, txid);
1874-
return;
1875+
return Ok(());
18751876
}
18761877
}
18771878

@@ -1885,21 +1886,33 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18851886
// block. Even if not, its a reasonable metric for the bump criteria on the HTLC
18861887
// transactions.
18871888
let (claim_reqs, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, self.best_block.height());
1888-
self.onchain_tx_handler.update_claims_view(&Vec::new(), claim_reqs, self.best_block.height(), self.best_block.height(), broadcaster, fee_estimator, logger);
1889+
if self.onchain_tx_handler.update_claims_view(&Vec::new(), claim_reqs, self.best_block.height(), self.best_block.height(), broadcaster, fee_estimator, logger).is_err() {
1890+
log_warn!(logger, "Unable to broadcast claims because signer is unavailable, will retry");
1891+
}
18891892
if let Some(ref tx) = self.prev_holder_signed_commitment_tx {
18901893
let (claim_reqs, _) = self.get_broadcasted_holder_claims(&tx, self.best_block.height());
1891-
self.onchain_tx_handler.update_claims_view(&Vec::new(), claim_reqs, self.best_block.height(), self.best_block.height(), broadcaster, fee_estimator, logger);
1894+
if self.onchain_tx_handler.update_claims_view(&Vec::new(), claim_reqs, self.best_block.height(), self.best_block.height(), broadcaster, fee_estimator, logger).is_err() {
1895+
log_warn!(logger, "Unable to broadcast claims for prev tx because signer is unavailable, will retry");
1896+
}
18921897
}
18931898
}
1899+
Ok(())
18941900
}
18951901

18961902
pub(crate) fn broadcast_latest_holder_commitment_txn<B: Deref, L: Deref>(&mut self, broadcaster: &B, logger: &L)
18971903
where B::Target: BroadcasterInterface,
18981904
L::Target: Logger,
18991905
{
1900-
for tx in self.get_latest_holder_commitment_txn(logger).iter() {
1901-
log_info!(logger, "Broadcasting local {}", log_tx!(tx));
1902-
broadcaster.broadcast_transaction(tx);
1906+
match self.get_latest_holder_commitment_txn(logger) {
1907+
Ok(txs) => {
1908+
for tx in txs.iter() {
1909+
log_info!(logger, "Broadcasting local {}", log_tx!(tx));
1910+
broadcaster.broadcast_transaction(tx);
1911+
}
1912+
}
1913+
Err(_) => {
1914+
log_warn!(logger, "Unable to broadcast holder tx because signer is unavailable, will retry");
1915+
}
19031916
}
19041917
self.pending_monitor_events.push(MonitorEvent::CommitmentTxConfirmed(self.funding_info.0));
19051918
}
@@ -1945,7 +1958,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
19451958
},
19461959
ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } => {
19471960
log_trace!(logger, "Updating ChannelMonitor with payment preimage");
1948-
self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, fee_estimator, logger)
1961+
// No further error handling needed
1962+
let _ = self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, fee_estimator, logger);
19491963
},
19501964
ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => {
19511965
log_trace!(logger, "Updating ChannelMonitor with commitment secret");
@@ -2291,10 +2305,11 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22912305
}
22922306
}
22932307

2294-
pub fn get_latest_holder_commitment_txn<L: Deref>(&mut self, logger: &L) -> Vec<Transaction> where L::Target: Logger {
2308+
pub fn get_latest_holder_commitment_txn<L: Deref>(&mut self, logger: &L) -> Result<Vec<Transaction>, SignError>
2309+
where L::Target: Logger {
22952310
log_debug!(logger, "Getting signed latest holder commitment transaction!");
22962311
self.holder_tx_signed = true;
2297-
let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript);
2312+
let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript)?;
22982313
let txid = commitment_tx.txid();
22992314
let mut holder_transactions = vec![commitment_tx];
23002315
for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() {
@@ -2313,14 +2328,14 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
23132328
continue;
23142329
} else { None };
23152330
if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(
2316-
&::bitcoin::OutPoint { txid, vout }, &preimage) {
2331+
&::bitcoin::OutPoint { txid, vout }, &preimage)? {
23172332
holder_transactions.push(htlc_tx);
23182333
}
23192334
}
23202335
}
23212336
// We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
23222337
// The data will be re-generated and tracked in check_spend_holder_transaction if we get a confirmation.
2323-
holder_transactions
2338+
Ok(holder_transactions)
23242339
}
23252340

23262341
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
@@ -2504,17 +2519,24 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
25042519
let commitment_package = PackageTemplate::build_package(self.funding_info.0.txid.clone(), self.funding_info.0.index as u32, PackageSolvingData::HolderFundingOutput(funding_outp), self.best_block.height(), false, self.best_block.height());
25052520
claimable_outpoints.push(commitment_package);
25062521
self.pending_monitor_events.push(MonitorEvent::CommitmentTxConfirmed(self.funding_info.0));
2507-
let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript);
25082522
self.holder_tx_signed = true;
2509-
// Because we're broadcasting a commitment transaction, we should construct the package
2510-
// assuming it gets confirmed in the next block. Sadly, we have code which considers
2511-
// "not yet confirmed" things as discardable, so we cannot do that here.
2512-
let (mut new_outpoints, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, self.best_block.height());
2513-
let new_outputs = self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, &commitment_tx);
2514-
if !new_outputs.is_empty() {
2515-
watch_outputs.push((self.current_holder_commitment_tx.txid.clone(), new_outputs));
2523+
match self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript) {
2524+
Ok(commitment_tx) => {
2525+
// Because we're broadcasting a commitment transaction, we should construct the package
2526+
// assuming it gets confirmed in the next block. Sadly, we have code which considers
2527+
// "not yet confirmed" things as discardable, so we cannot do that here.
2528+
let (mut new_outpoints, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, self.best_block.height());
2529+
let new_outputs = self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, &commitment_tx);
2530+
if !new_outputs.is_empty() {
2531+
watch_outputs.push((self.current_holder_commitment_tx.txid.clone(), new_outputs));
2532+
}
2533+
claimable_outpoints.append(&mut new_outpoints);
2534+
2535+
}
2536+
Err(_) => {
2537+
log_warn!(logger, "Unable to broadcast holder commitment tx because the signer is not available, will retry");
2538+
}
25162539
}
2517-
claimable_outpoints.append(&mut new_outpoints);
25182540
}
25192541

25202542
// Find which on-chain events have reached their confirmation threshold.
@@ -2587,7 +2609,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
25872609
}
25882610
}
25892611

2590-
self.onchain_tx_handler.update_claims_view(&txn_matched, claimable_outpoints, conf_height, self.best_block.height(), broadcaster, fee_estimator, logger);
2612+
if self.onchain_tx_handler.update_claims_view(&txn_matched, claimable_outpoints, conf_height, self.best_block.height(), broadcaster, fee_estimator, logger).is_err() {
2613+
log_warn!(logger, "Unable to broadcast claims because signer was not available, will retry");
2614+
}
25912615

25922616
// Determine new outputs to watch by comparing against previously known outputs to watch,
25932617
// updating the latter in the process.
@@ -3580,7 +3604,7 @@ mod tests {
35803604
monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key, &logger);
35813605
monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key, &logger);
35823606
for &(ref preimage, ref hash) in preimages.iter() {
3583-
monitor.provide_payment_preimage(hash, preimage, &broadcaster, &fee_estimator, &logger);
3607+
monitor.provide_payment_preimage(hash, preimage, &broadcaster, &fee_estimator, &logger).unwrap();
35843608
}
35853609

35863610
// Now provide a secret, pruning preimages 10-15

lightning/src/chain/keysinterface.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,15 @@ impl_writeable_tlv_based_enum!(SpendableOutputDescriptor,
187187
(2, StaticPaymentOutput),
188188
);
189189

190+
/// An error while signing
191+
#[derive(Debug)]
192+
pub enum SignError {
193+
/// The signer is temporarily unavailable
194+
Temporary,
195+
/// A signer internal error
196+
Internal
197+
}
198+
190199
/// A trait to sign lightning channel transactions as described in BOLT 3.
191200
///
192201
/// Signing services could be implemented on a hardware wallet. In this case,
@@ -278,7 +287,7 @@ pub trait BaseSign {
278287
//
279288
// TODO: Document the things someone using this interface should enforce before signing.
280289
// TODO: Key derivation failure should panic rather than Err
281-
fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()>;
290+
fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), SignError>;
282291

283292
/// Same as sign_holder_commitment, but exists only for tests to get access to holder commitment
284293
/// transactions which will be broadcasted later, after the channel has moved on to a newer
@@ -683,13 +692,14 @@ impl BaseSign for InMemorySigner {
683692
Ok(())
684693
}
685694

686-
fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()> {
695+
fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), SignError> {
687696
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
688697
let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
689698
let trusted_tx = commitment_tx.trust();
690699
let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
691700
let channel_parameters = self.get_channel_parameters();
692-
let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?;
701+
let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)
702+
.map_err(|()| SignError::Internal)?;
693703
Ok((sig, htlc_sigs))
694704
}
695705

0 commit comments

Comments
 (0)