mirror of
https://github.com/lightningnetwork/lnd.git
synced 2026-08-14 12:42:48 +02:00
chanstate: add open channel lifecycle store
Add a lifecycle subinterface to the chanstate Store contract for refresh, confirmation, open-state, and SCID mutations. Implement the subinterface on ChannelStateDB using the existing KV persistence code. Update the matching OpenChannel receivers to call through the store methods instead of reaching into the ChannelStateDB backend directly. Also convert fullSync into a channeldb helper so that KV-specific code is no longer an OpenChannel receiver.
This commit is contained in:
parent
444e80c0d9
commit
849d097625
2 changed files with 196 additions and 103 deletions
|
|
@ -1127,9 +1127,16 @@ func (c *OpenChannel) Refresh() error {
|
|||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
|
||||
return c.Db.RefreshChannel(c)
|
||||
}
|
||||
|
||||
// RefreshChannel updates the in-memory channel state using the latest state
|
||||
// observed on disk.
|
||||
func (c *ChannelStateDB) RefreshChannel(channel *OpenChannel) error {
|
||||
return kvdb.View(c.backend, func(tx kvdb.RTx) error {
|
||||
chanBucket, err := fetchChanBucket(
|
||||
tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
|
||||
tx, channel.IdentityPub, &channel.FundingOutpoint,
|
||||
channel.ChainHash,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -1137,30 +1144,27 @@ func (c *OpenChannel) Refresh() error {
|
|||
|
||||
// We'll re-populating the in-memory channel with the info
|
||||
// fetched from disk.
|
||||
if err := fetchChanInfo(chanBucket, c); err != nil {
|
||||
if err := fetchChanInfo(chanBucket, channel); err != nil {
|
||||
return fmt.Errorf("unable to fetch chan info: %w", err)
|
||||
}
|
||||
|
||||
// Also populate the channel's commitment states for both sides
|
||||
// of the channel.
|
||||
if err := fetchChanCommitments(chanBucket, c); err != nil {
|
||||
err = fetchChanCommitments(chanBucket, channel)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to fetch chan commitments: "+
|
||||
"%v", err)
|
||||
}
|
||||
|
||||
// Also retrieve the current revocation state.
|
||||
if err := fetchChanRevocationState(chanBucket, c); err != nil {
|
||||
err = fetchChanRevocationState(chanBucket, channel)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to fetch chan revocations: "+
|
||||
"%v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, func() {})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// fetchChanBucket is a helper function that returns the bucket where a
|
||||
|
|
@ -1301,9 +1305,9 @@ func fetchFinalHtlcsBucketRw(tx kvdb.RwTx,
|
|||
return chanBucket, nil
|
||||
}
|
||||
|
||||
// fullSync syncs the contents of an OpenChannel while re-using an existing
|
||||
// database transaction.
|
||||
func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
|
||||
// fullSyncOpenChannel syncs the contents of an OpenChannel while re-using an
|
||||
// existing database transaction.
|
||||
func fullSyncOpenChannel(tx kvdb.RwTx, c *OpenChannel) error {
|
||||
// Fetch the outpoint bucket and check if the outpoint already exists.
|
||||
opBucket := tx.ReadWriteBucket(outpointBucket)
|
||||
if opBucket == nil {
|
||||
|
|
@ -1399,23 +1403,7 @@ 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 {
|
||||
if err := c.Db.MarkChannelConfirmationHeight(c, height); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -1424,6 +1412,33 @@ func (c *OpenChannel) MarkConfirmationHeight(height uint32) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// MarkChannelConfirmationHeight updates the channel's confirmation height once
|
||||
// the channel opening transaction receives one confirmation.
|
||||
func (c *ChannelStateDB) MarkChannelConfirmationHeight(channel *OpenChannel,
|
||||
height uint32) error {
|
||||
|
||||
return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
|
||||
chanBucket, err := fetchChanBucketRw(
|
||||
tx, channel.IdentityPub, &channel.FundingOutpoint,
|
||||
channel.ChainHash,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskChannel, err := fetchOpenChannel(
|
||||
chanBucket, &channel.FundingOutpoint,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskChannel.ConfirmationHeight = height
|
||||
|
||||
return putOpenChannel(chanBucket, diskChannel)
|
||||
}, func() {})
|
||||
}
|
||||
|
||||
// ResetCloseConfirmationHeight clears the channel's close confirmation height
|
||||
// when the spending transaction is reorged out.
|
||||
func (c *OpenChannel) ResetCloseConfirmationHeight() error {
|
||||
|
|
@ -1438,23 +1453,8 @@ func (c *OpenChannel) MarkCloseConfirmationHeight(
|
|||
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.CloseConfirmationHeight = height
|
||||
|
||||
return putOpenChannel(chanBucket, channel)
|
||||
}, func() {}); err != nil {
|
||||
err := c.Db.MarkChannelCloseConfirmationHeight(c, height)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -1463,30 +1463,40 @@ func (c *OpenChannel) MarkCloseConfirmationHeight(
|
|||
return nil
|
||||
}
|
||||
|
||||
// MarkChannelCloseConfirmationHeight updates the channel's close confirmation
|
||||
// height when the closing transaction is first detected in a block.
|
||||
func (c *ChannelStateDB) MarkChannelCloseConfirmationHeight(
|
||||
channel *OpenChannel, height fn.Option[uint32]) error {
|
||||
|
||||
return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
|
||||
chanBucket, err := fetchChanBucketRw(
|
||||
tx, channel.IdentityPub, &channel.FundingOutpoint,
|
||||
channel.ChainHash,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskChannel, err := fetchOpenChannel(
|
||||
chanBucket, &channel.FundingOutpoint,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskChannel.CloseConfirmationHeight = height
|
||||
|
||||
return putOpenChannel(chanBucket, diskChannel)
|
||||
}, func() {})
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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.IsPending = false
|
||||
channel.ShortChannelID = openLoc
|
||||
|
||||
return putOpenChannel(chanBucket, channel)
|
||||
}, func() {}); err != nil {
|
||||
if err := c.Db.MarkChannelOpen(c, openLoc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -1497,31 +1507,41 @@ func (c *OpenChannel) MarkAsOpen(openLoc lnwire.ShortChannelID) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// MarkChannelOpen marks a channel as fully open given a locator that uniquely
|
||||
// describes its location within the chain.
|
||||
func (c *ChannelStateDB) MarkChannelOpen(channel *OpenChannel,
|
||||
openLoc lnwire.ShortChannelID) error {
|
||||
|
||||
return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
|
||||
chanBucket, err := fetchChanBucketRw(
|
||||
tx, channel.IdentityPub, &channel.FundingOutpoint,
|
||||
channel.ChainHash,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskChannel, err := fetchOpenChannel(
|
||||
chanBucket, &channel.FundingOutpoint,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskChannel.IsPending = false
|
||||
diskChannel.ShortChannelID = openLoc
|
||||
|
||||
return putOpenChannel(chanBucket, diskChannel)
|
||||
}, func() {})
|
||||
}
|
||||
|
||||
// MarkRealScid marks the zero-conf channel's confirmed ShortChannelID. This
|
||||
// should only be done if IsZeroConf returns true.
|
||||
func (c *OpenChannel) MarkRealScid(realScid lnwire.ShortChannelID) 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.confirmedScid = realScid
|
||||
|
||||
return putOpenChannel(chanBucket, channel)
|
||||
}, func() {}); err != nil {
|
||||
if err := c.Db.MarkChannelRealScid(c, realScid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -1530,30 +1550,39 @@ func (c *OpenChannel) MarkRealScid(realScid lnwire.ShortChannelID) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// MarkChannelRealScid marks the zero-conf channel's confirmed ShortChannelID.
|
||||
func (c *ChannelStateDB) MarkChannelRealScid(channel *OpenChannel,
|
||||
realScid lnwire.ShortChannelID) error {
|
||||
|
||||
return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
|
||||
chanBucket, err := fetchChanBucketRw(
|
||||
tx, channel.IdentityPub, &channel.FundingOutpoint,
|
||||
channel.ChainHash,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskChannel, err := fetchOpenChannel(
|
||||
chanBucket, &channel.FundingOutpoint,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskChannel.confirmedScid = realScid
|
||||
|
||||
return putOpenChannel(chanBucket, diskChannel)
|
||||
}, func() {})
|
||||
}
|
||||
|
||||
// MarkScidAliasNegotiated adds ScidAliasFeatureBit to ChanType in-memory and
|
||||
// in the database.
|
||||
func (c *OpenChannel) MarkScidAliasNegotiated() 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.ChanType |= ScidAliasFeatureBit
|
||||
return putOpenChannel(chanBucket, channel)
|
||||
}, func() {}); err != nil {
|
||||
if err := c.Db.MarkChannelScidAliasNegotiated(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -1562,6 +1591,33 @@ func (c *OpenChannel) MarkScidAliasNegotiated() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// MarkChannelScidAliasNegotiated adds ScidAliasFeatureBit to ChanType in the
|
||||
// database.
|
||||
func (c *ChannelStateDB) MarkChannelScidAliasNegotiated(
|
||||
channel *OpenChannel) error {
|
||||
|
||||
return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
|
||||
chanBucket, err := fetchChanBucketRw(
|
||||
tx, channel.IdentityPub, &channel.FundingOutpoint,
|
||||
channel.ChainHash,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskChannel, err := fetchOpenChannel(
|
||||
chanBucket, &channel.FundingOutpoint,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskChannel.ChanType |= ScidAliasFeatureBit
|
||||
|
||||
return putOpenChannel(chanBucket, diskChannel)
|
||||
}, func() {})
|
||||
}
|
||||
|
||||
// MarkDataLoss marks sets the channel status to LocalDataLoss and stores the
|
||||
// passed commitPoint for use to retrieve funds in case the remote force closes
|
||||
// the channel.
|
||||
|
|
@ -2215,7 +2271,7 @@ func (c *OpenChannel) SyncPending(addr net.Addr, pendingHeight uint32) error {
|
|||
// LinkNode (if needed) for the channel peer.
|
||||
func syncNewChannel(tx kvdb.RwTx, c *OpenChannel, addrs []net.Addr) error {
|
||||
// First, sync all the persistent channel state to disk.
|
||||
if err := c.fullSync(tx); err != nil {
|
||||
if err := fullSyncOpenChannel(tx, c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package chanstate
|
|||
import (
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/wire/v2"
|
||||
"github.com/lightningnetwork/lnd/fn/v2"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
|
@ -23,6 +24,10 @@ type Store[Channel any] interface {
|
|||
// HistoricalChannelStore owns the post-close historical channel view.
|
||||
HistoricalChannelStore[Channel]
|
||||
|
||||
// OpenChannelLifecycleStore owns persisted lifecycle state for open
|
||||
// channel records.
|
||||
OpenChannelLifecycleStore[Channel]
|
||||
|
||||
// ClosedChannelStore owns closed-channel summaries and lifecycle
|
||||
// mutations.
|
||||
ClosedChannelStore[Channel]
|
||||
|
|
@ -103,6 +108,38 @@ type HistoricalChannelStore[Channel any] interface {
|
|||
FetchHistoricalChannel(outPoint *wire.OutPoint) (Channel, error)
|
||||
}
|
||||
|
||||
// OpenChannelLifecycleStore owns persisted lifecycle state for open channel
|
||||
// records.
|
||||
type OpenChannelLifecycleStore[Channel any] interface {
|
||||
// RefreshChannel updates the in-memory channel state using the latest
|
||||
// state observed on disk.
|
||||
RefreshChannel(channel Channel) error
|
||||
|
||||
// MarkChannelConfirmationHeight updates the channel's confirmation
|
||||
// height once the channel opening transaction receives one
|
||||
// confirmation.
|
||||
MarkChannelConfirmationHeight(channel Channel, height uint32) error
|
||||
|
||||
// MarkChannelCloseConfirmationHeight updates the channel's close
|
||||
// confirmation height when the closing transaction is first detected
|
||||
// in a block.
|
||||
MarkChannelCloseConfirmationHeight(channel Channel,
|
||||
height fn.Option[uint32]) error
|
||||
|
||||
// MarkChannelOpen marks a channel as fully open given a locator that
|
||||
// uniquely describes its location within the chain.
|
||||
MarkChannelOpen(channel Channel, openLoc lnwire.ShortChannelID) error
|
||||
|
||||
// MarkChannelRealScid marks the zero-conf channel's confirmed
|
||||
// ShortChannelID.
|
||||
MarkChannelRealScid(channel Channel,
|
||||
realScid lnwire.ShortChannelID) error
|
||||
|
||||
// MarkChannelScidAliasNegotiated marks that the scid-alias feature
|
||||
// bit was negotiated during the lifetime of the channel.
|
||||
MarkChannelScidAliasNegotiated(channel Channel) error
|
||||
}
|
||||
|
||||
// ClosedChannelStore owns closed-channel summaries and lifecycle mutations.
|
||||
type ClosedChannelStore[Channel any] interface {
|
||||
// FetchClosedChannels attempts to fetch all closed channels from the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue