Skip to content

Commit 9c4cb91

Browse files
committed
Re-order ConstructedTransaction::new checks
An upcoming commit will include the contributed inputs and outputs in an error whenever ConstructedTransaction::new fails. In order to DRY up that logic, this commit updates the constructor to create the resulting object prior to performing any checks. This way a conversion method can be added that extracts the necessary input and output data.
1 parent dea125a commit 9c4cb91

File tree

1 file changed

+24
-30
lines changed

1 file changed

+24
-30
lines changed

lightning/src/ln/interactivetxs.rs

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -248,62 +248,56 @@ impl_writeable_tlv_based!(ConstructedTransaction, {
248248

249249
impl ConstructedTransaction {
250250
fn new(context: NegotiationContext) -> Result<Self, AbortReason> {
251-
if let Some(shared_funding_input) = &context.shared_funding_input {
252-
if !context.inputs.iter().any(|(_, input)| {
253-
input.txin().previous_output == shared_funding_input.input.previous_output
254-
}) {
255-
return Err(AbortReason::MissingFundingInput);
256-
}
257-
}
258-
if !context
259-
.outputs
260-
.iter()
261-
.any(|(_, output)| *output.tx_out() == context.shared_funding_output.tx_out)
262-
{
263-
return Err(AbortReason::MissingFundingOutput);
264-
}
265-
266251
let satisfaction_weight =
267252
Weight::from_wu(context.inputs.iter().fold(0u64, |value, (_, input)| {
268253
value.saturating_add(input.satisfaction_weight().to_wu())
269254
}));
270255

256+
let lock_time = context.tx_locktime;
257+
271258
let mut inputs: Vec<(TxIn, TxInMetadata)> =
272259
context.inputs.into_values().map(|input| input.into_txin_and_metadata()).collect();
273260
let mut outputs: Vec<(TxOut, TxOutMetadata)> =
274261
context.outputs.into_values().map(|output| output.into_txout_and_metadata()).collect();
275262
inputs.sort_unstable_by_key(|(_, input)| input.serial_id);
276263
outputs.sort_unstable_by_key(|(_, output)| output.serial_id);
277264

265+
let (input, input_metadata): (Vec<TxIn>, Vec<TxInMetadata>) = inputs.into_iter().unzip();
266+
let (output, output_metadata): (Vec<TxOut>, Vec<TxOutMetadata>) =
267+
outputs.into_iter().unzip();
268+
278269
let shared_input_index =
279270
context.shared_funding_input.as_ref().and_then(|shared_funding_input| {
280-
inputs
271+
input
281272
.iter()
282-
.position(|(txin, _)| {
273+
.position(|txin| {
283274
txin.previous_output == shared_funding_input.input.previous_output
284275
})
285276
.map(|position| position as u32)
286277
});
287278

288-
let (input, input_metadata): (Vec<TxIn>, Vec<TxInMetadata>) = inputs.into_iter().unzip();
289-
let (output, output_metadata): (Vec<TxOut>, Vec<TxOutMetadata>) =
290-
outputs.into_iter().unzip();
279+
let tx = ConstructedTransaction {
280+
holder_is_initiator: context.holder_is_initiator,
281+
input_metadata,
282+
output_metadata,
283+
tx: Transaction { version: Version::TWO, lock_time, input, output },
284+
shared_input_index,
285+
};
286+
287+
if context.shared_funding_input.is_some() && tx.shared_input_index.is_none() {
288+
return Err(AbortReason::MissingFundingInput);
289+
}
291290

292-
let tx =
293-
Transaction { version: Version::TWO, lock_time: context.tx_locktime, input, output };
291+
if !tx.tx.output.iter().any(|txout| *txout == context.shared_funding_output.tx_out) {
292+
return Err(AbortReason::MissingFundingOutput);
293+
}
294294

295-
let tx_weight = tx.weight().checked_add(satisfaction_weight).unwrap_or(Weight::MAX);
295+
let tx_weight = tx.tx.weight().checked_add(satisfaction_weight).unwrap_or(Weight::MAX);
296296
if tx_weight > Weight::from_wu(MAX_STANDARD_TX_WEIGHT as u64) {
297297
return Err(AbortReason::TransactionTooLarge);
298298
}
299299

300-
Ok(Self {
301-
holder_is_initiator: context.holder_is_initiator,
302-
input_metadata,
303-
output_metadata,
304-
tx,
305-
shared_input_index,
306-
})
300+
Ok(tx)
307301
}
308302

309303
pub fn tx(&self) -> &Transaction {

0 commit comments

Comments
 (0)