What changed, and why it matters
This commit is a straightforward internal code reorganization. It moves the logic for loading, acknowledging, and removing HTLC forwarding packages from the OpenChannel type to a new ChannelStateDB store interface. The actual database operations and locking behavior remain unchanged. There is no indication this fixes or introduces a security vulnerability.
No security action required. Review as normal refactoring if auditing for correctness, but the diff does not warrant incident response or patch prioritization on security grounds.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change refactors forwarding-package storage methods (LoadFwdPkgs, AckAddHtlcs, AckSettleFails, SetFwdFilter, RemoveFwdPkgs) out of OpenChannel receivers and into ChannelStateDB, then exposes them via a new OpenChannelFwdPkgStore interface in chanstate.Store. The OpenChannel methods now delegate to c.Db. The kvdb transaction bodies, Packager calls, and RLock/Lock patterns are preserved verbatim. This is an abstraction-layer refactor with no functional change to data access or concurrency control.
Changed components
channeldb/channel.gochanstate/interface.goInspect captured patch +82 / −10
diff --git a/channeldb/channel.go b/channeldb/channel.go
index 33598c0..3972916 100644
--- a/channeldb/channel.go
+++ b/channeldb/channel.go
@@ -3421,10 +3421,19 @@ func (c *OpenChannel) LoadFwdPkgs() ([]*FwdPkg, error) {
c.RLock()
defer c.RUnlock()
+ return c.Db.LoadFwdPkgs(c)
+}
+
+// LoadFwdPkgs scans the forwarding log for any packages that haven't been
+// processed, and returns their deserialized log updates in map indexed by the
+// remote commitment height at which the updates were locked in.
+func (c *ChannelStateDB) LoadFwdPkgs(channel *OpenChannel) ([]*FwdPkg,
+ error) {
+
var fwdPkgs []*FwdPkg
- if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
+ if err := kvdb.View(c.backend, func(tx kvdb.RTx) error {
var err error
- fwdPkgs, err = c.Packager.LoadFwdPkgs(tx)
+ fwdPkgs, err = channel.Packager.LoadFwdPkgs(tx)
return err
}, func() {
fwdPkgs = nil
@@ -3442,8 +3451,17 @@ func (c *OpenChannel) AckAddHtlcs(addRefs ...AddRef) error {
c.Lock()
defer c.Unlock()
- return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
- return c.Packager.AckAddHtlcs(tx, addRefs...)
+ return c.Db.AckAddHtlcs(c, addRefs...)
+}
+
+// AckAddHtlcs updates the AckAddFilter containing any of the provided AddRefs
+// indicating that a response to this Add has been committed to the remote party.
+// Doing so will prevent these Add HTLCs from being reforwarded internally.
+func (c *ChannelStateDB) AckAddHtlcs(channel *OpenChannel,
+ addRefs ...AddRef) error {
+
+ return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
+ return channel.Packager.AckAddHtlcs(tx, addRefs...)
}, func() {})
}
@@ -3455,8 +3473,18 @@ func (c *OpenChannel) AckSettleFails(settleFailRefs ...SettleFailRef) error {
c.Lock()
defer c.Unlock()
- return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
- return c.Packager.AckSettleFails(tx, settleFailRefs...)
+ return c.Db.AckSettleFails(c, settleFailRefs...)
+}
+
+// AckSettleFails updates the SettleFailFilter containing any of the provided
+// SettleFailRefs, indicating that the response has been delivered to the
+// incoming link, corresponding to a particular AddRef. Doing so will prevent
+// the responses from being retransmitted internally.
+func (c *ChannelStateDB) AckSettleFails(channel *OpenChannel,
+ settleFailRefs ...SettleFailRef) error {
+
+ return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
+ return channel.Packager.AckSettleFails(tx, settleFailRefs...)
}, func() {})
}
@@ -3466,8 +3494,16 @@ func (c *OpenChannel) SetFwdFilter(height uint64, fwdFilter *PkgFilter) error {
c.Lock()
defer c.Unlock()
- return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
- return c.Packager.SetFwdFilter(tx, height, fwdFilter)
+ return c.Db.SetFwdFilter(c, height, fwdFilter)
+}
+
+// SetFwdFilter atomically sets the forwarding filter for the forwarding package
+// identified by `height`.
+func (c *ChannelStateDB) SetFwdFilter(channel *OpenChannel, height uint64,
+ fwdFilter *PkgFilter) error {
+
+ return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
+ return channel.Packager.SetFwdFilter(tx, height, fwdFilter)
}, func() {})
}
@@ -3480,9 +3516,20 @@ func (c *OpenChannel) RemoveFwdPkgs(heights ...uint64) error {
c.Lock()
defer c.Unlock()
- return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
+ return c.Db.RemoveFwdPkgs(c, heights...)
+}
+
+// RemoveFwdPkgs atomically removes forwarding packages specified by the remote
+// commitment heights. If one of the intermediate RemovePkg calls fails, then the
+// later packages won't be removed.
+//
+// NOTE: This method should only be called on packages marked FwdStateCompleted.
+func (c *ChannelStateDB) RemoveFwdPkgs(channel *OpenChannel,
+ heights ...uint64) error {
+
+ return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
for _, height := range heights {
- err := c.Packager.RemovePkg(tx, height)
+ err := channel.Packager.RemovePkg(tx, height)
if err != nil {
return err
}
diff --git a/chanstate/interface.go b/chanstate/interface.go
index 8a68fd4..919f997 100644
--- a/chanstate/interface.go
+++ b/chanstate/interface.go
@@ -45,6 +45,10 @@ type Store[Channel any] interface {
// channel records.
OpenChannelCommitmentStore[Channel]
+ // OpenChannelFwdPkgStore owns forwarding packages tied to open
+ // channel records.
+ OpenChannelFwdPkgStore[Channel]
+
// ClosedChannelStore owns closed-channel summaries and lifecycle
// mutations.
ClosedChannelStore[Channel]
@@ -262,6 +266,27 @@ type OpenChannelCommitmentStore[Channel any] interface {
theirOutputIndex uint32) error
}
+// OpenChannelFwdPkgStore owns forwarding packages tied to open channel records.
+type OpenChannelFwdPkgStore[Channel any] interface {
+ // LoadFwdPkgs loads forwarding packages that have not been processed.
+ LoadFwdPkgs(channel Channel) ([]*FwdPkg, error)
+
+ // AckAddHtlcs marks add HTLCs in forwarding packages as resolved.
+ AckAddHtlcs(channel Channel, addRefs ...AddRef) error
+
+ // AckSettleFails marks settles or fails as delivered to the incoming
+ // link.
+ AckSettleFails(channel Channel, settleFailRefs ...SettleFailRef) error
+
+ // SetFwdFilter writes the forwarding filter for the forwarding package
+ // identified by height.
+ SetFwdFilter(channel Channel, height uint64, fwdFilter *PkgFilter) error
+
+ // RemoveFwdPkgs removes forwarding packages by remote commitment
+ // height.
+ RemoveFwdPkgs(channel Channel, heights ...uint64) error
+}
+
// ClosedChannelStore owns closed-channel summaries and lifecycle mutations.
type ClosedChannelStore[Channel any] interface {
// FetchClosedChannels attempts to fetch all closed channels from the
Why this scored 13/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.