Skip to content

Commit 2918c4a

Browse files
committed
Refactor channel funding transaction fields
1 parent 9c9e5f8 commit 2918c4a

File tree

3 files changed

+241
-52
lines changed

3 files changed

+241
-52
lines changed

lightning/src/ln/chan_utils.rs

Lines changed: 205 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use bitcoin::util::address::Payload;
1919
use bitcoin::hashes::{Hash, HashEngine};
2020
use bitcoin::hashes::sha256::Hash as Sha256;
2121
use bitcoin::hashes::ripemd160::Hash as Ripemd160;
22-
use bitcoin::hash_types::{Txid, PubkeyHash, WPubkeyHash};
22+
use bitcoin::hash_types::{BlockHash, Txid, PubkeyHash, WPubkeyHash};
2323

2424
use crate::chain::chaininterface::fee_for_weight;
2525
use crate::chain::package::WEIGHT_REVOKED_OUTPUT;
@@ -858,6 +858,210 @@ pub fn build_anchor_input_witness(funding_key: &PublicKey, funding_sig: &Signatu
858858
ret
859859
}
860860

861+
pub(crate) struct ChannelFundingTransaction {
862+
tx: Option<Transaction>,
863+
txo: Option<chain::transaction::OutPoint>,
864+
/// The hash of the block in which the funding transaction was included.
865+
tx_confirmed_in: Option<BlockHash>,
866+
tx_confirmation_height: Option<u32>,
867+
}
868+
869+
/// Stores into about a funding transaction:
870+
/// - TX outpoint and/or the full Transaction
871+
/// - confirmation block/height for confirmed transactions
872+
impl ChannelFundingTransaction {
873+
pub(crate) fn new_empty() -> Self {
874+
Self { tx: None, txo: None, tx_confirmed_in: None, tx_confirmation_height: None }
875+
}
876+
877+
pub(crate) fn get_tx(&self) -> Option<&Transaction> { self.tx.as_ref() }
878+
879+
pub(crate) fn set_tx(&mut self, tx: Transaction) {
880+
self.tx = Some(tx);
881+
}
882+
883+
pub(crate) fn set_txo(&mut self, txo: chain::transaction::OutPoint) {
884+
self.txo = Some(txo);
885+
}
886+
887+
pub(crate) fn is_confirmed(&self) -> bool {
888+
self.tx_confirmation_height.is_some() && self.tx_confirmed_in.is_some()
889+
}
890+
891+
/// Returns the current number of confirmations
892+
pub(crate) fn get_tx_confirmations(&mut self, height: u32) -> Option<i64> {
893+
match self.tx_confirmation_height {
894+
// We either haven't seen any confirmation yet, or observed a reorg.
895+
None => None,
896+
Some(h) => {
897+
let confs = height as i64 - h as i64 + 1;
898+
// Reset on reorg
899+
if confs <= 0 {
900+
self.tx_confirmation_height = None;
901+
}
902+
Some(confs)
903+
}
904+
}
905+
}
906+
907+
/// Returns the current number of confirmations
908+
pub(crate) fn get_tx_confirmations_nocheck(&self, height: u32) -> Option<u32> {
909+
match self.tx_confirmation_height {
910+
// We either haven't seen any confirmation yet, or observed a reorg.
911+
None => None,
912+
Some(h) => height.checked_sub(h).map(|c| c + 1)
913+
}
914+
}
915+
916+
fn set_confirmed(&mut self, block_hash: BlockHash, block_height: u32) {
917+
// TODO check if confirmed already
918+
self.tx_confirmed_in = Some(block_hash);
919+
self.tx_confirmation_height = Some(block_height);
920+
}
921+
922+
// fn reset_unconfirmed(&mut self) {
923+
// self.tx_confirmed_in = None;
924+
// self.tx_confirmation_height = None;
925+
// }
926+
927+
pub(crate) fn get_tx_confirmed_in(&self) -> Option<BlockHash> { self.tx_confirmed_in }
928+
pub(crate) fn get_tx_confirmation_height(&self) -> Option<u32> { self.tx_confirmation_height }
929+
}
930+
931+
impl Writeable for ChannelFundingTransaction {
932+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
933+
self.tx.write(writer)?;
934+
self.txo.write(writer)?;
935+
self.tx_confirmed_in.write(writer)?;
936+
self.tx_confirmation_height.write(writer)?;
937+
Ok(())
938+
}
939+
}
940+
941+
impl Readable for ChannelFundingTransaction {
942+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
943+
let tx = Readable::read(reader)?;
944+
let txo = Readable::read(reader)?;
945+
let tx_confirmed_in = Readable::read(reader)?;
946+
let tx_confirmation_height = Readable::read(reader)?;
947+
Ok(Self { tx, txo, tx_confirmed_in, tx_confirmation_height })
948+
}
949+
}
950+
951+
/// Stores info about zero or one funding transaction:
952+
/// - none in case of unfunded channels
953+
/// 1 in case of funded channels (can be uncofirmed or confirmed)
954+
/// It is prepared to handle multiple funding transaction candidates (e.g. in case of Splicing)
955+
pub(crate) struct ChannelFundingTransactions {
956+
tx: Option<ChannelFundingTransaction>,
957+
}
958+
959+
impl ChannelFundingTransactions {
960+
pub(crate) fn new_empty() -> Self {
961+
Self { tx: None }
962+
}
963+
964+
pub(crate) fn is_some(&self) -> bool {
965+
self.tx.is_some()
966+
}
967+
968+
pub(crate) fn set_tx(&mut self, tx: Transaction) {
969+
if let Some(cft) = self.tx.as_mut() {
970+
cft.set_tx(tx);
971+
} else {
972+
let mut cft = ChannelFundingTransaction::new_empty();
973+
cft.set_tx(tx);
974+
self.tx = Some(cft);
975+
}
976+
}
977+
978+
pub(crate) fn set_txo(&mut self, txo: chain::transaction::OutPoint) {
979+
if let Some(cft) = self.tx.as_mut() {
980+
cft.set_txo(txo);
981+
} else {
982+
let mut cft = ChannelFundingTransaction::new_empty();
983+
cft.set_txo(txo);
984+
self.tx = Some(cft);
985+
}
986+
}
987+
988+
pub(crate) fn is_confirmed(&self) -> bool {
989+
self.tx.as_ref().map_or(false, |tx| tx.is_confirmed())
990+
// match &self.tx {
991+
// None => false,
992+
// Some(tx) => tx.is_confirmed(),
993+
// }
994+
}
995+
996+
pub(crate) fn is_unconfirmed(&self) -> bool {
997+
self.tx.as_ref().map_or(true, |tx| !tx.is_confirmed())
998+
}
999+
1000+
pub(crate) fn set_confirmed(&mut self, block_hash: BlockHash, block_height: u32) {
1001+
if let Some(tx) = self.tx.as_mut() {
1002+
tx.set_confirmed(block_hash, block_height);
1003+
} else {
1004+
panic!("Set_confirmed() invoked, but there is no funding tx!");
1005+
}
1006+
}
1007+
1008+
pub(crate) fn get_tx(&self) -> Option<Transaction> {
1009+
match &self.tx {
1010+
None => None,
1011+
Some(tx) => match tx.get_tx() {
1012+
None => None,
1013+
Some(tx) => Some(tx.clone()),
1014+
}
1015+
}
1016+
}
1017+
1018+
pub(crate) fn tx_take(&mut self) -> Option<Transaction> {
1019+
match self.tx.take() {
1020+
None => None,
1021+
Some(tx) => match tx.get_tx() {
1022+
None => None,
1023+
Some(tx) => Some(tx.clone())
1024+
}
1025+
}
1026+
}
1027+
1028+
/// Returns the block hash in the funding transaction was confirmed.
1029+
pub(crate) fn get_tx_confirmed_in(&self) -> Option<BlockHash> {
1030+
match &self.tx {
1031+
None => None,
1032+
Some(tx) => tx.get_tx_confirmed_in(),
1033+
}
1034+
}
1035+
1036+
pub(crate) fn get_tx_confirmation_height(&self) -> Option<u32> {
1037+
self.tx.as_ref().map_or(None, |tx| tx.get_tx_confirmation_height())
1038+
}
1039+
1040+
/// Returns the current number of confirmations
1041+
pub(crate) fn get_tx_confirmations(&mut self, height: u32) -> Option<i64> {
1042+
self.tx.as_mut().map_or(None, |tx| tx.get_tx_confirmations(height))
1043+
}
1044+
1045+
/// Returns the current number of confirmations
1046+
pub(crate) fn get_tx_confirmations_nocheck(&self, height: u32) -> Option<u32> {
1047+
self.tx.as_ref().map_or(None, |tx| tx.get_tx_confirmations_nocheck(height))
1048+
}
1049+
}
1050+
1051+
impl Writeable for ChannelFundingTransactions {
1052+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
1053+
self.tx.write(writer)?;
1054+
Ok(())
1055+
}
1056+
}
1057+
1058+
impl Readable for ChannelFundingTransactions {
1059+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
1060+
let tx = Readable::read(reader)?;
1061+
Ok(Self { tx })
1062+
}
1063+
}
1064+
8611065
/// Per-channel data used to build transactions in conjunction with the per-commitment data (CommitmentTransaction).
8621066
/// The fields are organized by holder/counterparty.
8631067
///

0 commit comments

Comments
 (0)