Skip to content

Commit e06ab61

Browse files
committed
Remove TransactionU16LenLimited
TransactionU16LenLimited was used to limit Transaction serialization size to u16::MAX. This was because messages can not be longer than u16::MAX bytes when serialized for the transport layer. However, this limit doesn't take into account other fields in a message containing a Transaction, including the length of the transaction itself. Remove TransactionU16LenLimited and instead check any user supplied transactions in the context of the enclosing message (e.g. TxAddInput).
1 parent e42bed3 commit e06ab61

File tree

6 files changed

+110
-124
lines changed

6 files changed

+110
-124
lines changed

lightning/src/ln/channel.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ use crate::ln::onion_utils::{
7272
};
7373
use crate::ln::script::{self, ShutdownScript};
7474
use crate::ln::types::ChannelId;
75+
#[cfg(splicing)]
76+
use crate::ln::LN_MAX_MSG_LEN;
7577
use crate::routing::gossip::NodeId;
7678
use crate::sign::ecdsa::EcdsaChannelSigner;
7779
use crate::sign::tx_builder::{SpecTxBuilder, TxBuilder};
@@ -85,9 +87,7 @@ use crate::util::config::{
8587
use crate::util::errors::APIError;
8688
use crate::util::logger::{Logger, Record, WithContext};
8789
use crate::util::scid_utils::{block_from_scid, scid_from_parts};
88-
use crate::util::ser::{
89-
Readable, ReadableArgs, RequiredWrapper, TransactionU16LenLimited, Writeable, Writer,
90-
};
90+
use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, Writeable, Writer};
9191

9292
use alloc::collections::{btree_map, BTreeMap};
9393

@@ -5978,7 +5978,7 @@ pub(super) struct FundingNegotiationContext {
59785978
pub shared_funding_input: Option<SharedOwnedInput>,
59795979
/// The funding inputs we will be contributing to the channel.
59805980
#[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled.
5981-
pub our_funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>,
5981+
pub our_funding_inputs: Vec<(TxIn, Transaction)>,
59825982
/// The change output script. This will be used if needed or -- if not set -- generated using
59835983
/// `SignerProvider::get_destination_script`.
59845984
#[allow(dead_code)] // TODO(splicing): Remove once splicing is enabled.
@@ -10670,10 +10670,26 @@ where
1067010670
})?;
1067110671
// Convert inputs
1067210672
let mut funding_inputs = Vec::new();
10673-
for (tx_in, tx, _w) in our_funding_inputs.into_iter() {
10674-
let tx16 = TransactionU16LenLimited::new(tx)
10675-
.map_err(|_e| APIError::APIMisuseError { err: format!("Too large transaction") })?;
10676-
funding_inputs.push((tx_in, tx16));
10673+
for (txin, tx, _) in our_funding_inputs.into_iter() {
10674+
const MESSAGE_TEMPLATE: msgs::TxAddInput = msgs::TxAddInput {
10675+
channel_id: ChannelId([0; 32]),
10676+
serial_id: 0,
10677+
prevtx: None,
10678+
prevtx_out: 0,
10679+
sequence: 0,
10680+
shared_input_txid: None,
10681+
};
10682+
let message_len = MESSAGE_TEMPLATE.serialized_length() + tx.serialized_length();
10683+
if message_len > LN_MAX_MSG_LEN {
10684+
return Err(APIError::APIMisuseError {
10685+
err: format!(
10686+
"Funding input references a prevtx that is too large for tx_add_input: {}",
10687+
txin.previous_output,
10688+
),
10689+
});
10690+
}
10691+
10692+
funding_inputs.push((txin, tx));
1067710693
}
1067810694

1067910695
let prev_funding_input = self.funding.to_splice_funding_input();
@@ -12452,7 +12468,7 @@ where
1245212468
pub fn new_outbound<ES: Deref, F: Deref, L: Deref>(
1245312469
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
1245412470
counterparty_node_id: PublicKey, their_features: &InitFeatures, funding_satoshis: u64,
12455-
funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>, user_id: u128, config: &UserConfig,
12471+
funding_inputs: Vec<(TxIn, Transaction)>, user_id: u128, config: &UserConfig,
1245612472
current_chain_height: u32, outbound_scid_alias: u64, funding_confirmation_target: ConfirmationTarget,
1245712473
logger: L,
1245812474
) -> Result<Self, APIError>

lightning/src/ln/dual_funding_tests.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use {
2323
crate::ln::msgs::{CommitmentSigned, TxAddInput, TxAddOutput, TxComplete, TxSignatures},
2424
crate::ln::types::ChannelId,
2525
crate::prelude::*,
26-
crate::util::ser::TransactionU16LenLimited,
2726
crate::util::test_utils,
2827
bitcoin::Witness,
2928
};
@@ -51,7 +50,7 @@ fn do_test_v2_channel_establishment(session: V2ChannelEstablishmentTestSession)
5150
&[session.initiator_input_value_satoshis],
5251
)
5352
.into_iter()
54-
.map(|(txin, tx, _)| (txin, TransactionU16LenLimited::new(tx).unwrap()))
53+
.map(|(txin, tx, _)| (txin, tx))
5554
.collect();
5655

5756
// Alice creates a dual-funded channel as initiator.
@@ -94,7 +93,7 @@ fn do_test_v2_channel_establishment(session: V2ChannelEstablishmentTestSession)
9493
sequence: initiator_funding_inputs[0].0.sequence.0,
9594
shared_input_txid: None,
9695
};
97-
let input_value = tx_add_input_msg.prevtx.as_ref().unwrap().as_transaction().output
96+
let input_value = tx_add_input_msg.prevtx.as_ref().unwrap().output
9897
[tx_add_input_msg.prevtx_out as usize]
9998
.value;
10099
assert_eq!(input_value.to_sat(), session.initiator_input_value_satoshis);

lightning/src/ln/interactivetxs.rs

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ use crate::ln::msgs;
3232
use crate::ln::msgs::{MessageSendEvent, SerialId, TxSignatures};
3333
use crate::ln::types::ChannelId;
3434
use crate::sign::{EntropySource, P2TR_KEY_PATH_WITNESS_WEIGHT, P2WPKH_WITNESS_WEIGHT};
35-
use crate::util::ser::TransactionU16LenLimited;
3635

3736
use core::fmt::Display;
3837
use core::ops::Deref;
@@ -869,10 +868,9 @@ impl NegotiationContext {
869868
return Err(AbortReason::UnexpectedFundingInput);
870869
}
871870
} else if let Some(prevtx) = &msg.prevtx {
872-
let transaction = prevtx.as_transaction();
873-
let txid = transaction.compute_txid();
871+
let txid = prevtx.compute_txid();
874872

875-
if let Some(tx_out) = transaction.output.get(msg.prevtx_out as usize) {
873+
if let Some(tx_out) = prevtx.output.get(msg.prevtx_out as usize) {
876874
if !tx_out.script_pubkey.is_witness_program() {
877875
// The receiving node:
878876
// - MUST fail the negotiation if:
@@ -1053,14 +1051,9 @@ impl NegotiationContext {
10531051
return Err(AbortReason::UnexpectedFundingInput);
10541052
}
10551053
} else if let Some(prevtx) = &msg.prevtx {
1056-
let prev_txid = prevtx.as_transaction().compute_txid();
1054+
let prev_txid = prevtx.compute_txid();
10571055
let prev_outpoint = OutPoint { txid: prev_txid, vout: msg.prevtx_out };
1058-
let prev_output = prevtx
1059-
.as_transaction()
1060-
.output
1061-
.get(vout)
1062-
.ok_or(AbortReason::PrevTxOutInvalid)?
1063-
.clone();
1056+
let prev_output = prevtx.output.get(vout).ok_or(AbortReason::PrevTxOutInvalid)?.clone();
10641057
let txin = TxIn {
10651058
previous_output: prev_outpoint,
10661059
sequence: Sequence(msg.sequence),
@@ -1441,7 +1434,7 @@ impl_writeable_tlv_based_enum!(AddingRole,
14411434
#[derive(Clone, Debug, Eq, PartialEq)]
14421435
struct SingleOwnedInput {
14431436
input: TxIn,
1444-
prev_tx: TransactionU16LenLimited,
1437+
prev_tx: Transaction,
14451438
prev_output: TxOut,
14461439
}
14471440

@@ -1843,7 +1836,7 @@ where
18431836
pub feerate_sat_per_kw: u32,
18441837
pub is_initiator: bool,
18451838
pub funding_tx_locktime: AbsoluteLockTime,
1846-
pub inputs_to_contribute: Vec<(TxIn, TransactionU16LenLimited)>,
1839+
pub inputs_to_contribute: Vec<(TxIn, Transaction)>,
18471840
pub shared_funding_input: Option<SharedOwnedInput>,
18481841
pub shared_funding_output: SharedOwnedOutput,
18491842
pub outputs_to_contribute: Vec<TxOut>,
@@ -1885,7 +1878,7 @@ impl InteractiveTxConstructor {
18851878
// Check for the existence of prevouts'
18861879
for (txin, tx) in inputs_to_contribute.iter() {
18871880
let vout = txin.previous_output.vout as usize;
1888-
if tx.as_transaction().output.get(vout).is_none() {
1881+
if tx.output.get(vout).is_none() {
18891882
return Err(AbortReason::PrevTxOutInvalid);
18901883
}
18911884
}
@@ -1894,7 +1887,7 @@ impl InteractiveTxConstructor {
18941887
.map(|(txin, tx)| {
18951888
let serial_id = generate_holder_serial_id(entropy_source, is_initiator);
18961889
let vout = txin.previous_output.vout as usize;
1897-
let prev_output = tx.as_transaction().output.get(vout).unwrap().clone(); // checked above
1890+
let prev_output = tx.output.get(vout).unwrap().clone(); // checked above
18981891
let input =
18991892
InputOwned::Single(SingleOwnedInput { input: txin, prev_tx: tx, prev_output });
19001893
(serial_id, input)
@@ -2083,12 +2076,11 @@ pub(super) fn calculate_change_output_value(
20832076
let mut total_input_satoshis = 0u64;
20842077
let mut our_funding_inputs_weight = 0u64;
20852078
for (txin, tx) in context.our_funding_inputs.iter() {
2086-
let txid = tx.as_transaction().compute_txid();
2079+
let txid = tx.compute_txid();
20872080
if txin.previous_output.txid != txid {
20882081
return Err(AbortReason::PrevTxOutInvalid);
20892082
}
20902083
let output = tx
2091-
.as_transaction()
20922084
.output
20932085
.get(txin.previous_output.vout as usize)
20942086
.ok_or(AbortReason::PrevTxOutInvalid)?;
@@ -2145,7 +2137,6 @@ mod tests {
21452137
use crate::ln::types::ChannelId;
21462138
use crate::sign::EntropySource;
21472139
use crate::util::atomic_counter::AtomicCounter;
2148-
use crate::util::ser::TransactionU16LenLimited;
21492140
use bitcoin::absolute::LockTime as AbsoluteLockTime;
21502141
use bitcoin::amount::Amount;
21512142
use bitcoin::hashes::Hash;
@@ -2211,12 +2202,12 @@ mod tests {
22112202

22122203
struct TestSession {
22132204
description: &'static str,
2214-
inputs_a: Vec<(TxIn, TransactionU16LenLimited)>,
2205+
inputs_a: Vec<(TxIn, Transaction)>,
22152206
a_shared_input: Option<(OutPoint, TxOut, u64)>,
22162207
/// The funding output, with the value contributed
22172208
shared_output_a: (TxOut, u64),
22182209
outputs_a: Vec<TxOut>,
2219-
inputs_b: Vec<(TxIn, TransactionU16LenLimited)>,
2210+
inputs_b: Vec<(TxIn, Transaction)>,
22202211
b_shared_input: Option<(OutPoint, TxOut, u64)>,
22212212
/// The funding output, with the value contributed
22222213
shared_output_b: (TxOut, u64),
@@ -2482,7 +2473,7 @@ mod tests {
24822473
}
24832474
}
24842475

2485-
fn generate_inputs(outputs: &[TestOutput]) -> Vec<(TxIn, TransactionU16LenLimited)> {
2476+
fn generate_inputs(outputs: &[TestOutput]) -> Vec<(TxIn, Transaction)> {
24862477
let tx = generate_tx(outputs);
24872478
let txid = tx.compute_txid();
24882479
tx.output
@@ -2495,7 +2486,7 @@ mod tests {
24952486
sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
24962487
witness: Default::default(),
24972488
};
2498-
(txin, TransactionU16LenLimited::new(tx.clone()).unwrap())
2489+
(txin, tx.clone())
24992490
})
25002491
.collect()
25012492
}
@@ -2543,12 +2534,12 @@ mod tests {
25432534
(generate_txout(&TestOutput::P2WSH(value)), local_value)
25442535
}
25452536

2546-
fn generate_fixed_number_of_inputs(count: u16) -> Vec<(TxIn, TransactionU16LenLimited)> {
2537+
fn generate_fixed_number_of_inputs(count: u16) -> Vec<(TxIn, Transaction)> {
25472538
// Generate transactions with a total `count` number of outputs such that no transaction has a
25482539
// serialized length greater than u16::MAX.
25492540
let max_outputs_per_prevtx = 1_500;
25502541
let mut remaining = count;
2551-
let mut inputs: Vec<(TxIn, TransactionU16LenLimited)> = Vec::with_capacity(count as usize);
2542+
let mut inputs: Vec<(TxIn, Transaction)> = Vec::with_capacity(count as usize);
25522543

25532544
while remaining > 0 {
25542545
let tx_output_count = remaining.min(max_outputs_per_prevtx);
@@ -2561,7 +2552,7 @@ mod tests {
25612552
);
25622553
let txid = tx.compute_txid();
25632554

2564-
let mut temp: Vec<(TxIn, TransactionU16LenLimited)> = tx
2555+
let mut temp: Vec<(TxIn, Transaction)> = tx
25652556
.output
25662557
.iter()
25672558
.enumerate()
@@ -2572,7 +2563,7 @@ mod tests {
25722563
sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
25732564
witness: Default::default(),
25742565
};
2575-
(input, TransactionU16LenLimited::new(tx.clone()).unwrap())
2566+
(input, tx.clone())
25762567
})
25772568
.collect();
25782569

@@ -2783,10 +2774,9 @@ mod tests {
27832774
expect_error: Some((AbortReason::PrevTxOutInvalid, ErrorCulprit::NodeA)),
27842775
});
27852776

2786-
let tx =
2787-
TransactionU16LenLimited::new(generate_tx(&[TestOutput::P2WPKH(1_000_000)])).unwrap();
2777+
let tx = generate_tx(&[TestOutput::P2WPKH(1_000_000)]);
27882778
let invalid_sequence_input = TxIn {
2789-
previous_output: OutPoint { txid: tx.as_transaction().compute_txid(), vout: 0 },
2779+
previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 },
27902780
..Default::default()
27912781
};
27922782
do_test_interactive_tx_constructor(TestSession {
@@ -2802,7 +2792,7 @@ mod tests {
28022792
expect_error: Some((AbortReason::IncorrectInputSequenceValue, ErrorCulprit::NodeA)),
28032793
});
28042794
let duplicate_input = TxIn {
2805-
previous_output: OutPoint { txid: tx.as_transaction().compute_txid(), vout: 0 },
2795+
previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 },
28062796
sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
28072797
..Default::default()
28082798
};
@@ -2820,7 +2810,7 @@ mod tests {
28202810
});
28212811
// Non-initiator uses same prevout as initiator.
28222812
let duplicate_input = TxIn {
2823-
previous_output: OutPoint { txid: tx.as_transaction().compute_txid(), vout: 0 },
2813+
previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 },
28242814
sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
28252815
..Default::default()
28262816
};
@@ -2837,7 +2827,7 @@ mod tests {
28372827
expect_error: Some((AbortReason::PrevTxOutInvalid, ErrorCulprit::NodeA)),
28382828
});
28392829
let duplicate_input = TxIn {
2840-
previous_output: OutPoint { txid: tx.as_transaction().compute_txid(), vout: 0 },
2830+
previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 },
28412831
sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
28422832
..Default::default()
28432833
};
@@ -3170,9 +3160,9 @@ mod tests {
31703160
sequence: Sequence::ZERO,
31713161
witness: Witness::new(),
31723162
};
3173-
(txin, TransactionU16LenLimited::new(tx).unwrap())
3163+
(txin, tx)
31743164
})
3175-
.collect::<Vec<(TxIn, TransactionU16LenLimited)>>();
3165+
.collect::<Vec<(TxIn, Transaction)>>();
31763166
let our_contributed = 110_000;
31773167
let txout = TxOut { value: Amount::from_sat(10_000), script_pubkey: ScriptBuf::new() };
31783168
let outputs = vec![txout];

0 commit comments

Comments
 (0)