Merge pull request #9677 from NishantBansal2003/conf-count

Expose confirmation count for pending 'channel open' transactions
This commit is contained in:
Yong authored and GitHub committed 2025-09-11 22:36:05 +08:00
commit 5082566ed7
14 files changed
+2928 -2151

No files matched your search

+47
View File
@@ -261,6 +261,10 @@ type openChannelTlvData struct {
// customBlob is an optional TLV encoded blob of data representing
// custom channel funding information.
customBlob tlv.OptionalRecordT[tlv.TlvType7, tlv.Blob]
// confirmationHeight records the block height at which the funding
// transaction was first confirmed.
confirmationHeight tlv.RecordT[tlv.TlvType8, uint32]
}
// encode serializes the openChannelTlvData to the given io.Writer.
@@ -270,6 +274,7 @@ func (c *openChannelTlvData) encode(w io.Writer) error {
c.initialLocalBalance.Record(),
c.initialRemoteBalance.Record(),
c.realScid.Record(),
c.confirmationHeight.Record(),
}
c.memo.WhenSome(func(memo tlv.RecordT[tlv.TlvType5, []byte]) {
tlvRecords = append(tlvRecords, memo.Record())
@@ -283,6 +288,8 @@ func (c *openChannelTlvData) encode(w io.Writer) error {
tlvRecords = append(tlvRecords, blob.Record())
})
tlv.SortRecords(tlvRecords)
// Create the tlv stream.
tlvStream, err := tlv.NewStream(tlvRecords...)
if err != nil {
@@ -307,6 +314,7 @@ func (c *openChannelTlvData) decode(r io.Reader) error {
memo.Record(),
tapscriptRoot.Record(),
blob.Record(),
c.confirmationHeight.Record(),
)
if err != nil {
return err
@@ -906,6 +914,10 @@ type OpenChannel struct {
// been confirmed before a certain height.
FundingBroadcastHeight uint32
// ConfirmationHeight records the block height at which the funding
// transaction was first confirmed.
ConfirmationHeight uint32
// NumConfsRequired is the number of confirmations a channel's funding
// transaction must have received in order to be considered available
// for normal transactional use.
@@ -1207,6 +1219,7 @@ func (c *OpenChannel) amendTlvData(auxData openChannelTlvData) {
auxData.initialRemoteBalance.Val,
)
c.confirmedScid = auxData.realScid.Val
c.ConfirmationHeight = auxData.confirmationHeight.Val
auxData.memo.WhenSomeV(func(memo []byte) {
c.Memo = memo
@@ -1234,6 +1247,9 @@ func (c *OpenChannel) extractTlvData() openChannelTlvData {
realScid: tlv.NewRecordT[tlv.TlvType4](
c.confirmedScid,
),
confirmationHeight: tlv.NewPrimitiveRecord[tlv.TlvType8](
c.ConfirmationHeight,
),
}
if len(c.Memo) != 0 {
@@ -1501,6 +1517,37 @@ func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
return putOpenChannel(chanBucket, c)
}
// MarkConfirmationHeight updates the channel's confirmation height once the
// channel opening transaction receives one confirmation.
func (c *OpenChannel) MarkConfirmationHeight(height uint32) error {
c.Lock()
defer c.Unlock()
if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
chanBucket, err := fetchChanBucketRw(
tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
)
if err != nil {
return err
}
channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
if err != nil {
return err
}
channel.ConfirmationHeight = height
return putOpenChannel(chanBucket, channel)
}, func() {}); err != nil {
return err
}
c.ConfirmationHeight = height
return nil
}
// MarkAsOpen marks a channel as fully open given a locator that uniquely
// describes its location within the chain.
func (c *OpenChannel) MarkAsOpen(openLoc lnwire.ShortChannelID) error {
+68 -1
View File
@@ -978,6 +978,73 @@ func TestChannelStateTransition(t *testing.T) {
require.Empty(t, fwdPkgs, "no forwarding packages should exist")
}
// TestOpeningChannelTxConfirmation verifies that calling MarkConfirmationHeight
// correctly updates the confirmed state. It also ensures that calling Refresh
// on a different OpenChannel updates its in-memory state to reflect the prior
// MarkConfirmationHeight call.
func TestOpeningChannelTxConfirmation(t *testing.T) {
t.Parallel()
fullDB, err := MakeTestDB(t)
require.NoError(t, err)
cdb := fullDB.ChannelStateDB()
// Create a pending channel that was broadcast at height 99.
const broadcastHeight = uint32(99)
channelState := createTestChannel(
t, cdb, pendingHeightOption(broadcastHeight),
)
// Fetch pending channels from the database.
pendingChannels, err := cdb.FetchPendingChannels()
require.NoError(t, err)
require.Len(t, pendingChannels, 1)
// Verify the broadcast height of the pending channel.
require.Equal(
t, broadcastHeight, pendingChannels[0].FundingBroadcastHeight,
)
confirmationHeight := broadcastHeight + 1
// Mark the channel's confirmation height.
err = pendingChannels[0].MarkConfirmationHeight(confirmationHeight)
require.NoError(t, err)
// Verify the ConfirmationHeight is updated correctly.
require.Equal(
t, confirmationHeight, pendingChannels[0].ConfirmationHeight,
)
// Re-fetch the pending channels to confirm persistence.
pendingChannels, err = cdb.FetchPendingChannels()
require.NoError(t, err)
require.Len(t, pendingChannels, 1)
// Validate the confirmation and broadcast height.
require.Equal(
t, confirmationHeight, pendingChannels[0].ConfirmationHeight,
)
require.Equal(
t, broadcastHeight, pendingChannels[0].FundingBroadcastHeight,
)
// Ensure the original channel state's confirmation height is not
// updated before refresh.
require.EqualValues(t, channelState.ConfirmationHeight, 0)
// Refresh the original channel state.
err = channelState.Refresh()
require.NoError(t, err)
// Verify that both channel states now have the same ConfirmationHeight.
require.Equal(
t, channelState.ConfirmationHeight,
pendingChannels[0].ConfirmationHeight,
)
}
func TestFetchPendingChannels(t *testing.T) {
t.Parallel()
@@ -1007,7 +1074,7 @@ func TestFetchPendingChannels(t *testing.T) {
}
chanOpenLoc := lnwire.ShortChannelID{
BlockHeight: 5,
BlockHeight: broadcastHeight + 1,
TxIndex: 10,
TxPosition: 15,
}