@@ -2246,21 +2246,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2246
2246
funding_inputs.push(prev_funding_input);
2247
2247
}
2248
2248
2249
- let mut funding_inputs_prev_outputs: Vec<&TxOut> = Vec::with_capacity(funding_inputs.len());
2250
- // Check that vouts exist for each TxIn in provided transactions.
2251
- for (idx, (txin, tx)) in funding_inputs.iter().enumerate() {
2252
- if let Some(output) = tx.as_transaction().output.get(txin.previous_output.vout as usize) {
2253
- funding_inputs_prev_outputs.push(output);
2254
- } else {
2255
- return Err(APIError::APIMisuseError {
2256
- err: format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
2257
- tx.as_transaction().compute_txid(), txin.previous_output.vout, idx) });
2258
- }
2259
- }
2249
+ let funding_inputs_prev_outputs = DualFundingChannelContext::txouts_from_input_prev_txs(&funding_inputs)
2250
+ .map_err(|err| APIError::APIMisuseError { err: err.to_string() })?;
2260
2251
2261
- let total_input_satoshis: u64 = funding_inputs.iter().map(
2262
- |(txin, tx)| tx.as_transaction().output.get(txin.previous_output.vout as usize).map(|out| out.value.to_sat()).unwrap_or(0)
2263
- ).sum();
2252
+ let total_input_satoshis: u64 = funding_inputs_prev_outputs.iter().map(|txout| txout.value.to_sat()).sum();
2264
2253
if total_input_satoshis < self.dual_funding_context.our_funding_satoshis {
2265
2254
return Err(APIError::APIMisuseError {
2266
2255
err: format!("Total value of funding inputs must be at least funding amount. It was {} sats",
@@ -5051,6 +5040,33 @@ pub(super) struct DualFundingChannelContext {
5051
5040
pub our_funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>,
5052
5041
}
5053
5042
5043
+ impl DualFundingChannelContext {
5044
+ /// Obtain prev outputs for each supplied input and matching transaction.
5045
+ /// Can error when there a prev tx does not have an output for the specified vout number.
5046
+ /// Also checks for matching of transaction IDs.
5047
+ fn txouts_from_input_prev_txs(inputs: &Vec<(TxIn, TransactionU16LenLimited)>) -> Result<Vec<&TxOut>, ChannelError> {
5048
+ let mut prev_outputs: Vec<&TxOut> = Vec::with_capacity(inputs.len());
5049
+ // Check that vouts exist for each TxIn in provided transactions.
5050
+ for (idx, (txin, tx)) in inputs.iter().enumerate() {
5051
+ let txid = tx.as_transaction().compute_txid();
5052
+ if txin.previous_output.txid != txid {
5053
+ return Err(ChannelError::Warn(
5054
+ format!("Transaction input txid mismatch, {} vs. {}, at index {}", txin.previous_output.txid, txid, idx)
5055
+ ));
5056
+ }
5057
+ if let Some(output) = tx.as_transaction().output.get(txin.previous_output.vout as usize) {
5058
+ prev_outputs.push(output);
5059
+ } else {
5060
+ return Err(ChannelError::Warn(
5061
+ format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn, at index {}",
5062
+ txid, txin.previous_output.vout, idx)
5063
+ ));
5064
+ }
5065
+ }
5066
+ Ok(prev_outputs)
5067
+ }
5068
+ }
5069
+
5054
5070
// Holder designates channel data owned for the benefit of the user client.
5055
5071
// Counterparty designates channel data owned by the another channel participant entity.
5056
5072
pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
@@ -10030,17 +10046,18 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
10030
10046
unfunded_channel_age_ticks: 0,
10031
10047
holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
10032
10048
};
10049
+ let dual_funding_context = DualFundingChannelContext {
10050
+ our_funding_satoshis: funding_satoshis,
10051
+ their_funding_satoshis: None,
10052
+ funding_tx_locktime,
10053
+ funding_feerate_sat_per_1000_weight,
10054
+ our_funding_inputs: funding_inputs,
10055
+ };
10033
10056
let chan = Self {
10034
10057
funding,
10035
10058
context,
10036
10059
unfunded_context,
10037
- dual_funding_context: DualFundingChannelContext {
10038
- our_funding_satoshis: funding_satoshis,
10039
- their_funding_satoshis: None,
10040
- funding_tx_locktime,
10041
- funding_feerate_sat_per_1000_weight,
10042
- our_funding_inputs: funding_inputs,
10043
- },
10060
+ dual_funding_context,
10044
10061
interactive_tx_constructor: None,
10045
10062
interactive_tx_signing_session: None,
10046
10063
};
0 commit comments