Skip to content

Commit 4f3c144

Browse files
committed
Implement logic for handling last tx_complete, signature for shared input
1 parent 5cf4329 commit 4f3c144

File tree

2 files changed

+48
-41
lines changed

2 files changed

+48
-41
lines changed

lightning/src/ln/channel.rs

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::ln::types::ChannelId;
3030
use crate::types::payment::{PaymentPreimage, PaymentHash};
3131
use crate::types::features::{ChannelTypeFeatures, InitFeatures};
3232
use crate::ln::interactivetxs::{
33-
calculate_change_output_value, get_output_weight, HandleTxCompleteValue, HandleTxCompleteResult, InteractiveTxConstructor,
33+
calculate_change_output_value, get_output_weight, AbortReason, HandleTxCompleteValue, HandleTxCompleteResult, InteractiveTxConstructor,
3434
InteractiveTxConstructorArgs, InteractiveTxMessageSend, InteractiveTxSigningSession, InteractiveTxMessageSendResult,
3535
OutputOwned, SharedOwnedOutput, TX_COMMON_FIELDS_WEIGHT,
3636
};
@@ -2221,13 +2221,15 @@ impl<SP: Deref> InitialRemoteCommitmentReceiver<SP> for FundedChannel<SP> where
22212221

22222222
impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22232223
/// Prepare and start interactive transaction negotiation.
2224-
/// `change_destination_opt` - Optional destination for optional change; if None, default destination address is used.
2224+
/// `change_destination_opt` - Optional destination for optional change; if None,
2225+
/// default destination address is used.
2226+
/// If error occurs, it is caused by our side, not the counterparty.
22252227
#[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled
22262228
fn begin_interactive_funding_tx_construction<ES: Deref>(
22272229
&mut self, signer_provider: &SP, entropy_source: &ES, holder_node_id: PublicKey,
22282230
change_destination_opt: Option<ScriptBuf>,
22292231
prev_funding_input: Option<(TxIn, TransactionU16LenLimited)>,
2230-
) -> Result<Option<InteractiveTxMessageSend>, ChannelError>
2232+
) -> Result<Option<InteractiveTxMessageSend>, AbortReason>
22312233
where ES::Target: EntropySource
22322234
{
22332235
debug_assert!(self.interactive_tx_constructor.is_none());
@@ -2271,19 +2273,14 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
22712273
script
22722274
} else {
22732275
signer_provider.get_destination_script(self.context.channel_keys_id)
2274-
.map_err(|err| ChannelError::Warn(format!(
2275-
"Failed to get change script as new destination script, {:?}", err,
2276-
)))?
2276+
.map_err(|_err| AbortReason::InternalErrorGettingDestinationScript)?
22772277
};
22782278
let change_value_opt = calculate_change_output_value(
22792279
self.funding.is_outbound(), self.dual_funding_context.our_funding_satoshis,
22802280
&funding_inputs_prev_outputs, &funding_outputs,
22812281
self.dual_funding_context.funding_feerate_sat_per_1000_weight,
22822282
change_script.minimal_non_dust().to_sat(),
2283-
).map_err(|err| ChannelError::Warn(format!(
2284-
"Insufficient inputs, cannot cover intended contribution of {} and fees; {}",
2285-
self.dual_funding_context.our_funding_satoshis, err
2286-
)))?;
2283+
)?;
22872284
if let Some(change_value) = change_value_opt {
22882285
let mut change_output = TxOut {
22892286
value: Amount::from_sat(change_value),
@@ -2311,8 +2308,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
23112308
outputs_to_contribute: funding_outputs,
23122309
expected_remote_shared_funding_output,
23132310
};
2314-
let mut tx_constructor = InteractiveTxConstructor::new(constructor_args)
2315-
.map_err(|_| ChannelError::Warn("Incorrect shared output provided".into()))?;
2311+
let mut tx_constructor = InteractiveTxConstructor::new(constructor_args)?;
23162312
let msg = tx_constructor.take_initiator_first_message();
23172313

23182314
self.interactive_tx_constructor = Some(tx_constructor);
@@ -4973,23 +4969,18 @@ impl DualFundingChannelContext {
49734969
/// Obtain prev outputs for each supplied input and matching transaction.
49744970
/// Will error when a prev tx does not have an output for the specified vout.
49754971
/// Also checks for matching of transaction IDs.
4976-
fn txouts_from_input_prev_txs(inputs: &Vec<(TxIn, TransactionU16LenLimited)>) -> Result<Vec<&TxOut>, ChannelError> {
4972+
fn txouts_from_input_prev_txs(inputs: &Vec<(TxIn, TransactionU16LenLimited)>) -> Result<Vec<&TxOut>, AbortReason> {
49774973
let mut prev_outputs: Vec<&TxOut> = Vec::with_capacity(inputs.len());
49784974
// Check that vouts exist for each TxIn in provided transactions.
49794975
for (idx, (txin, tx)) in inputs.iter().enumerate() {
49804976
let txid = tx.as_transaction().compute_txid();
49814977
if txin.previous_output.txid != txid {
4982-
return Err(ChannelError::Warn(
4983-
format!("Transaction input txid mismatch, {} vs. {}, at index {}", txin.previous_output.txid, txid, idx)
4984-
));
4978+
return Err(AbortReason::ProvidedInputsAndPrevtxsTxIdMismatch(idx as u32));
49854979
}
49864980
if let Some(output) = tx.as_transaction().output.get(txin.previous_output.vout as usize) {
49874981
prev_outputs.push(output);
49884982
} else {
4989-
return Err(ChannelError::Warn(
4990-
format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn, at index {}",
4991-
txid, txin.previous_output.vout, idx)
4992-
));
4983+
return Err(AbortReason::ProvidedInputsAndPrevtxsVoutNotFound(idx as u32));
49934984
}
49944985
}
49954986
Ok(prev_outputs)

lightning/src/ln/interactivetxs.rs

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ pub(crate) enum AbortReason {
108108
/// if funding output is provided by the peer this is an interop error,
109109
/// if provided by the same node than internal input consistency error.
110110
InvalidLowFundingOutputValue,
111+
/// TxId mismatch in the provided inputs and previous transactions, input index in data
112+
ProvidedInputsAndPrevtxsTxIdMismatch(u32),
113+
/// A vout provided in an input is not found in the matching previous transaction, input index in data
114+
ProvidedInputsAndPrevtxsVoutNotFound(u32),
115+
/// Internal error, error while getting destination script
116+
InternalErrorGettingDestinationScript,
111117
}
112118

113119
impl AbortReason {
@@ -118,34 +124,44 @@ impl AbortReason {
118124

119125
impl Display for AbortReason {
120126
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
121-
f.write_str(match self {
122-
AbortReason::InvalidStateTransition => "State transition was invalid",
123-
AbortReason::UnexpectedCounterpartyMessage => "Unexpected message",
124-
AbortReason::ReceivedTooManyTxAddInputs => "Too many `tx_add_input`s received",
125-
AbortReason::ReceivedTooManyTxAddOutputs => "Too many `tx_add_output`s received",
127+
f.write_str(&match self {
128+
AbortReason::InvalidStateTransition => "State transition was invalid".into(),
129+
AbortReason::UnexpectedCounterpartyMessage => "Unexpected message".into(),
130+
AbortReason::ReceivedTooManyTxAddInputs => "Too many `tx_add_input`s received".into(),
131+
AbortReason::ReceivedTooManyTxAddOutputs => "Too many `tx_add_output`s received".into(),
126132
AbortReason::IncorrectInputSequenceValue => {
127-
"Input has a sequence value greater than 0xFFFFFFFD"
133+
"Input has a sequence value greater than 0xFFFFFFFD".into()
128134
},
129-
AbortReason::IncorrectSerialIdParity => "Parity for `serial_id` was incorrect",
130-
AbortReason::SerialIdUnknown => "The `serial_id` is unknown",
131-
AbortReason::DuplicateSerialId => "The `serial_id` already exists",
132-
AbortReason::PrevTxOutInvalid => "Invalid previous transaction output",
135+
AbortReason::IncorrectSerialIdParity => "Parity for `serial_id` was incorrect".into(),
136+
AbortReason::SerialIdUnknown => "The `serial_id` is unknown".into(),
137+
AbortReason::DuplicateSerialId => "The `serial_id` already exists".into(),
138+
AbortReason::PrevTxOutInvalid => "Invalid previous transaction output".into(),
133139
AbortReason::ExceededMaximumSatsAllowed => {
134-
"Output amount exceeded total bitcoin supply"
140+
"Output amount exceeded total bitcoin supply".into()
135141
},
136-
AbortReason::ExceededNumberOfInputsOrOutputs => "Too many inputs or outputs",
137-
AbortReason::TransactionTooLarge => "Transaction weight is too large",
138-
AbortReason::BelowDustLimit => "Output amount is below the dust limit",
139-
AbortReason::InvalidOutputScript => "The output script is non-standard",
140-
AbortReason::InsufficientFees => "Insufficient fees paid",
142+
AbortReason::ExceededNumberOfInputsOrOutputs => "Too many inputs or outputs".into(),
143+
AbortReason::TransactionTooLarge => "Transaction weight is too large".into(),
144+
AbortReason::BelowDustLimit => "Output amount is below the dust limit".into(),
145+
AbortReason::InvalidOutputScript => "The output script is non-standard".into(),
146+
AbortReason::InsufficientFees => "Insufficient fees paid".into(),
141147
AbortReason::OutputsValueExceedsInputsValue => {
142-
"Total value of outputs exceeds total value of inputs"
148+
"Total value of outputs exceeds total value of inputs".into()
143149
},
144-
AbortReason::InvalidTx => "The transaction is invalid",
145-
AbortReason::MissingFundingOutput => "No shared funding output found",
146-
AbortReason::DuplicateFundingOutput => "More than one funding output found",
150+
AbortReason::InvalidTx => "The transaction is invalid".into(),
151+
AbortReason::MissingFundingOutput => "No shared funding output found".into(),
152+
AbortReason::DuplicateFundingOutput => "More than one funding output found".into(),
147153
AbortReason::InvalidLowFundingOutputValue => {
148-
"Local part of funding output value is greater than the funding output value"
154+
"Local part of funding output value is greater than the funding output value".into()
155+
},
156+
AbortReason::ProvidedInputsAndPrevtxsTxIdMismatch(idx) => format!(
157+
"TxId mismatch in the provided inputs and previous transactions, input index {}",
158+
idx
159+
),
160+
AbortReason::ProvidedInputsAndPrevtxsVoutNotFound(idx) => format!(
161+
"Vout provided in an input is not found in the previous transaction, input index {}",
162+
idx),
163+
AbortReason::InternalErrorGettingDestinationScript => {
164+
"Internal error getting destination script".into()
149165
},
150166
})
151167
}

0 commit comments

Comments
 (0)