@@ -1695,21 +1695,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
16951695 funding_inputs.push(prev_funding_input);
16961696 }
16971697
1698- let mut funding_inputs_prev_outputs: Vec<&TxOut> = Vec::with_capacity(funding_inputs.len());
1699- // Check that vouts exist for each TxIn in provided transactions.
1700- for (idx, (txin, tx)) in funding_inputs.iter().enumerate() {
1701- if let Some(output) = tx.as_transaction().output.get(txin.previous_output.vout as usize) {
1702- funding_inputs_prev_outputs.push(output);
1703- } else {
1704- return Err(APIError::APIMisuseError {
1705- err: format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
1706- tx.as_transaction().compute_txid(), txin.previous_output.vout, idx) });
1707- }
1708- }
1698+ let funding_inputs_prev_outputs = DualFundingChannelContext::txouts_from_input_prev_txs(&funding_inputs)
1699+ .map_err(|err| APIError::APIMisuseError { err: err.to_string() })?;
17091700
1710- let total_input_satoshis: u64 = funding_inputs.iter().map(
1711- |(txin, tx)| tx.as_transaction().output.get(txin.previous_output.vout as usize).map(|out| out.value.to_sat()).unwrap_or(0)
1712- ).sum();
1701+ let total_input_satoshis: u64 = funding_inputs_prev_outputs.iter().map(|txout| txout.value.to_sat()).sum();
17131702 if total_input_satoshis < self.dual_funding_context.our_funding_satoshis {
17141703 return Err(APIError::APIMisuseError {
17151704 err: format!("Total value of funding inputs must be at least funding amount. It was {} sats",
@@ -4269,6 +4258,33 @@ pub(super) struct DualFundingChannelContext {
42694258 pub our_funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>,
42704259}
42714260
4261+ impl DualFundingChannelContext {
4262+ /// Obtain prev outputs for each supplied input and matching transaction.
4263+ /// Can error when there a prev tx does not have an output for the specified vout number.
4264+ /// Also checks for matching of transaction IDs.
4265+ fn txouts_from_input_prev_txs(inputs: &Vec<(TxIn, TransactionU16LenLimited)>) -> Result<Vec<&TxOut>, ChannelError> {
4266+ let mut prev_outputs: Vec<&TxOut> = Vec::with_capacity(inputs.len());
4267+ // Check that vouts exist for each TxIn in provided transactions.
4268+ for (idx, (txin, tx)) in inputs.iter().enumerate() {
4269+ let txid = tx.as_transaction().compute_txid();
4270+ if txin.previous_output.txid != txid {
4271+ return Err(ChannelError::Warn(
4272+ format!("Transaction input txid mismatch, {} vs. {}, at index {}", txin.previous_output.txid, txid, idx)
4273+ ));
4274+ }
4275+ if let Some(output) = tx.as_transaction().output.get(txin.previous_output.vout as usize) {
4276+ prev_outputs.push(output);
4277+ } else {
4278+ return Err(ChannelError::Warn(
4279+ format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn, at index {}",
4280+ txid, txin.previous_output.vout, idx)
4281+ ));
4282+ }
4283+ }
4284+ Ok(prev_outputs)
4285+ }
4286+ }
4287+
42724288// Holder designates channel data owned for the benefit of the user client.
42734289// Counterparty designates channel data owned by the another channel participant entity.
42744290pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
@@ -8934,16 +8950,17 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
89348950 unfunded_channel_age_ticks: 0,
89358951 holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
89368952 };
8953+ let dual_funding_context = DualFundingChannelContext {
8954+ our_funding_satoshis: funding_satoshis,
8955+ their_funding_satoshis: None,
8956+ funding_tx_locktime,
8957+ funding_feerate_sat_per_1000_weight,
8958+ our_funding_inputs: funding_inputs,
8959+ };
89378960 let chan = Self {
89388961 context,
89398962 unfunded_context,
8940- dual_funding_context: DualFundingChannelContext {
8941- our_funding_satoshis: funding_satoshis,
8942- their_funding_satoshis: None,
8943- funding_tx_locktime,
8944- funding_feerate_sat_per_1000_weight,
8945- our_funding_inputs: funding_inputs,
8946- },
8963+ dual_funding_context,
89478964 interactive_tx_constructor: None,
89488965 };
89498966 Ok(chan)
0 commit comments