Skip to content

Commit 6b8249e

Browse files
committed
chanstate: introduce Store interface
Add a new chanstate package containing the Store interface plus a package logger. The interface mirrors the public surface of *channeldb.ChannelStateDB so the compile-time assertion var _ ChannelStore = (*channeldb.ChannelStateDB)(nil) No consumer migrates in this commit.
1 parent bb8eeb2 commit 6b8249e

3 files changed

Lines changed: 260 additions & 0 deletions

File tree

chanstate/interface.go

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
package chanstate
2+
3+
import (
4+
"github.com/btcsuite/btcd/btcec/v2"
5+
"github.com/btcsuite/btcd/wire"
6+
"github.com/lightningnetwork/lnd/channeldb"
7+
"github.com/lightningnetwork/lnd/graph/db/models"
8+
"github.com/lightningnetwork/lnd/lnwire"
9+
)
10+
11+
// Store is the full persistence contract for the channel-state subsystem.
12+
// Consumers depend on this interface rather than the concrete
13+
// channeldb.ChannelStateDB so the underlying storage can be swapped without
14+
// touching call sites.
15+
//
16+
// NOTE: This is named Store instead of DB to avoid confusion with the existing
17+
// concrete channeldb.ChannelStateDB type during the migration. Once the channel
18+
// state implementation moves into this package and the old concrete type is no
19+
// longer part of consumer-facing code, this name can be revisited.
20+
type Store interface {
21+
// OpenChannelStore owns open-channel records.
22+
OpenChannelStore
23+
24+
// HistoricalChannelStore owns the post-close historical channel view.
25+
HistoricalChannelStore
26+
27+
// ClosedChannelStore owns closed-channel summaries and lifecycle
28+
// mutations.
29+
ClosedChannelStore
30+
31+
// FinalHTLCStore owns final HTLC outcome data.
32+
FinalHTLCStore
33+
34+
// ChannelSetupStore owns temporary state used while setting up a
35+
// channel.
36+
ChannelSetupStore
37+
38+
// LinkNodeStore owns link-node side state derived from channel state.
39+
LinkNodeStore
40+
}
41+
42+
// OpenChannelStore owns open-channel records.
43+
type OpenChannelStore interface {
44+
// FetchOpenChannels starts a new database transaction and returns
45+
// all stored currently active/open channels associated with the
46+
// target nodeID. In the case that no active channels are known to
47+
// have been created with this node, then a zero-length slice is
48+
// returned.
49+
FetchOpenChannels(nodeID *btcec.PublicKey) (
50+
[]*channeldb.OpenChannel, error)
51+
52+
// FetchChannel attempts to locate a channel specified by the passed
53+
// channel point. If the channel cannot be found, then an error will
54+
// be returned.
55+
FetchChannel(chanPoint wire.OutPoint) (*channeldb.OpenChannel, error)
56+
57+
// FetchChannelByID attempts to locate a channel specified by the
58+
// passed channel ID. If the channel cannot be found, then an error
59+
// will be returned.
60+
FetchChannelByID(id lnwire.ChannelID) (*channeldb.OpenChannel, error)
61+
62+
// FetchAllChannels attempts to retrieve all open channels currently
63+
// stored within the database, including pending open, fully open and
64+
// channels waiting for a closing transaction to confirm.
65+
FetchAllChannels() ([]*channeldb.OpenChannel, error)
66+
67+
// FetchAllOpenChannels will return all channels that have the
68+
// funding transaction confirmed, and is not waiting for a closing
69+
// transaction to be confirmed.
70+
FetchAllOpenChannels() ([]*channeldb.OpenChannel, error)
71+
72+
// FetchPendingChannels will return channels that have completed the
73+
// process of generating and broadcasting funding transactions, but
74+
// whose funding transactions have yet to be confirmed on the
75+
// blockchain.
76+
FetchPendingChannels() ([]*channeldb.OpenChannel, error)
77+
78+
// FetchWaitingCloseChannels will return all channels that have been
79+
// opened, but are now waiting for a closing transaction to be
80+
// confirmed.
81+
//
82+
// NOTE: This includes channels that are also pending to be opened.
83+
FetchWaitingCloseChannels() ([]*channeldb.OpenChannel, error)
84+
85+
// FetchPermAndTempPeers returns a map where the key is the remote
86+
// node's public key and the value is a struct that has a tally of
87+
// the pending-open channels and whether the peer has an open or
88+
// closed channel with us.
89+
FetchPermAndTempPeers(chainHash []byte) (
90+
map[string]channeldb.ChanCount, error)
91+
92+
// RestoreChannelShells reconstructs the state of an OpenChannel from
93+
// the ChannelShell. We'll attempt to write the new channel to disk,
94+
// create a LinkNode instance with the passed node addresses, and
95+
// finally create an edge within the graph for the channel as well.
96+
// This method is idempotent, so repeated calls with the same set of
97+
// channel shells won't modify the database after the initial call.
98+
RestoreChannelShells(channelShells ...*channeldb.ChannelShell) error
99+
}
100+
101+
// HistoricalChannelStore owns the post-close historical channel view.
102+
type HistoricalChannelStore interface {
103+
// FetchHistoricalChannel fetches open channel data from the
104+
// historical channel bucket.
105+
FetchHistoricalChannel(outPoint *wire.OutPoint) (
106+
*channeldb.OpenChannel, error)
107+
}
108+
109+
// ClosedChannelStore owns closed-channel summaries and lifecycle mutations.
110+
type ClosedChannelStore interface {
111+
// FetchClosedChannels attempts to fetch all closed channels from the
112+
// database. The pendingOnly bool toggles if channels that aren't yet
113+
// fully closed should be returned in the response or not. When a
114+
// channel was cooperatively closed, it becomes fully closed after a
115+
// single confirmation. When a channel was forcibly closed, it will
116+
// become fully closed after _all_ the pending funds (if any) have
117+
// been swept.
118+
FetchClosedChannels(pendingOnly bool) (
119+
[]*channeldb.ChannelCloseSummary, error)
120+
121+
// FetchClosedChannel queries for a channel close summary using the
122+
// channel point of the channel in question.
123+
FetchClosedChannel(chanID *wire.OutPoint) (
124+
*channeldb.ChannelCloseSummary, error)
125+
126+
// FetchClosedChannelForID queries for a channel close summary using
127+
// the channel ID of the channel in question.
128+
FetchClosedChannelForID(cid lnwire.ChannelID) (
129+
*channeldb.ChannelCloseSummary, error)
130+
131+
// MarkChanFullyClosed marks a channel as fully closed within the
132+
// database. A channel should be marked as fully closed if the
133+
// channel was initially cooperatively closed and it's reached a
134+
// single confirmation, or after all the pending funds in a channel
135+
// that has been forcibly closed have been swept.
136+
MarkChanFullyClosed(chanPoint *wire.OutPoint) error
137+
138+
// CloseChannel marks the given channel as closed: the open-channel
139+
// record is removed and the supplied ChannelCloseSummary is
140+
// archived so the channel becomes retrievable via
141+
// FetchClosedChannel and FetchClosedChannelForID. Any ChannelStatus
142+
// values are merged into the archived summary. Returns
143+
// ErrChannelCloseSummaryNil if summary is nil.
144+
CloseChannel(channel *channeldb.OpenChannel,
145+
summary *channeldb.ChannelCloseSummary,
146+
statuses ...channeldb.ChannelStatus) error
147+
148+
// AbandonChannel attempts to remove the target channel from the open
149+
// channel database. If the channel was already removed (has a closed
150+
// channel entry), then we'll return a nil error. Otherwise, we'll
151+
// insert a new close summary into the database.
152+
AbandonChannel(chanPoint *wire.OutPoint, bestHeight uint32) error
153+
}
154+
155+
// FinalHTLCStore owns final HTLC outcome data.
156+
type FinalHTLCStore interface {
157+
// LookupFinalHtlc retrieves a final htlc resolution from the
158+
// database. If the htlc has no final resolution yet, ErrHtlcUnknown
159+
// is returned.
160+
LookupFinalHtlc(chanID lnwire.ShortChannelID,
161+
htlcIndex uint64) (*channeldb.FinalHtlcInfo, error)
162+
163+
// PutOnchainFinalHtlcOutcome stores the final on-chain outcome of an
164+
// htlc in the database.
165+
PutOnchainFinalHtlcOutcome(chanID lnwire.ShortChannelID,
166+
htlcID uint64, settled bool) error
167+
}
168+
169+
// ChannelSetupStore owns temporary state used while setting up a channel. This
170+
// state should be deleted once the link comes up.
171+
type ChannelSetupStore interface {
172+
// SaveChannelOpeningState saves the serialized channel state for the
173+
// provided chanPoint to the channelOpeningStateBucket.
174+
SaveChannelOpeningState(outPoint, serializedState []byte) error
175+
176+
// GetChannelOpeningState fetches the serialized channel state for
177+
// the provided outPoint from the database, or returns
178+
// ErrChannelNotFound if the channel is not found.
179+
GetChannelOpeningState(outPoint []byte) ([]byte, error)
180+
181+
// DeleteChannelOpeningState removes any state for outPoint from the
182+
// database.
183+
DeleteChannelOpeningState(outPoint []byte) error
184+
185+
// SaveInitialForwardingPolicy saves the serialized forwarding policy
186+
// for the provided permanent channel id.
187+
SaveInitialForwardingPolicy(chanID lnwire.ChannelID,
188+
forwardingPolicy *models.ForwardingPolicy) error
189+
190+
// GetInitialForwardingPolicy fetches the serialized forwarding policy
191+
// for the provided channel id from the database, or returns
192+
// ErrChannelNotFound if a forwarding policy for this channel id is not
193+
// found.
194+
GetInitialForwardingPolicy(chanID lnwire.ChannelID) (
195+
*models.ForwardingPolicy, error)
196+
197+
// DeleteInitialForwardingPolicy removes the forwarding policy for a
198+
// given channel from the database.
199+
DeleteInitialForwardingPolicy(chanID lnwire.ChannelID) error
200+
}
201+
202+
// LinkNodeStore owns link-node side state derived from channel state.
203+
type LinkNodeStore interface {
204+
// PruneLinkNodes attempts to prune all link nodes found within the
205+
// database with whom we no longer have any open channels with.
206+
PruneLinkNodes() error
207+
208+
// RepairLinkNodes scans all channels in the database and ensures
209+
// that a link node exists for each remote peer. This should be
210+
// called on startup to ensure that our database is consistent.
211+
RepairLinkNodes(network wire.BitcoinNet) error
212+
}
213+
214+
// Compile-time assertion that channeldb.ChannelStateDB satisfies the Store
215+
// contract. If a method signature drifts on the concrete type,
216+
// this assertion will fail to build before any consumer migration.
217+
//
218+
// NOTE: This assertion lives in the interface file as a temporary exception to
219+
// the established pattern (see invoices/sql_store.go, payments/db/kv_store.go,
220+
// graph/db/kv_store.go), where each implementation asserts itself in its own
221+
// file. The implementation still lives in channeldb/, and channeldb must not
222+
// import chanstate to avoid a cycle, so the assertion has no local
223+
// implementation file to live in yet. When the KV implementation moves into
224+
// this package (chanstate/kv_store.go), this assertion MUST be removed from
225+
// here and re-stated next to the local implementation, matching the precedent
226+
// packages.
227+
var _ Store = (*channeldb.ChannelStateDB)(nil)

chanstate/log.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package chanstate
2+
3+
import (
4+
"github.com/btcsuite/btclog/v2"
5+
"github.com/lightningnetwork/lnd/build"
6+
)
7+
8+
// log is a logger that is initialized with no output filters. This means the
9+
// package will not perform any logging by default until the caller requests
10+
// it.
11+
//
12+
//nolint:unused
13+
var log btclog.Logger
14+
15+
// init initializes the package-global logger instance.
16+
func init() {
17+
UseLogger(build.NewSubLogger("CHST", nil))
18+
}
19+
20+
// DisableLog disables all library log output. Logging output is disabled by
21+
// default until UseLogger is called.
22+
func DisableLog() {
23+
UseLogger(btclog.Disabled)
24+
}
25+
26+
// UseLogger uses a specified Logger to output package logging info. This
27+
// should be used in preference to SetLogWriter if the caller is also using
28+
// btclog.
29+
func UseLogger(logger btclog.Logger) {
30+
log = logger
31+
}

log.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/lightningnetwork/lnd/chanfitness"
1818
"github.com/lightningnetwork/lnd/channeldb"
1919
"github.com/lightningnetwork/lnd/channelnotifier"
20+
"github.com/lightningnetwork/lnd/chanstate"
2021
"github.com/lightningnetwork/lnd/cluster"
2122
"github.com/lightningnetwork/lnd/contractcourt"
2223
"github.com/lightningnetwork/lnd/discovery"
@@ -177,6 +178,7 @@ func SetupLoggers(root *build.SubLoggerManager, interceptor signal.Interceptor)
177178
AddSubLogger(root, "IRPC", interceptor, invoicesrpc.UseLogger)
178179
AddSubLogger(root, "CHNF", interceptor, channelnotifier.UseLogger)
179180
AddSubLogger(root, "CHBU", interceptor, chanbackup.UseLogger)
181+
AddSubLogger(root, "CHST", interceptor, chanstate.UseLogger)
180182
AddSubLogger(root, "PROM", interceptor, monitoring.UseLogger)
181183
AddSubLogger(root, "WTCL", interceptor, wtclient.UseLogger)
182184
AddSubLogger(root, "PRNF", interceptor, peernotifier.UseLogger)

0 commit comments

Comments
 (0)