mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-06-06 04:59:34 +02:00
Merge pull request #9236 from ellemouton/moveGraphDBCode
[1/3] Graph RIP: refactor+graph: move all graph related DB code to the graph package
This commit is contained in:
commit
506586a37e
@ -3,6 +3,7 @@ package autopilot
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"net"
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
@ -11,8 +12,8 @@ import (
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
@ -35,7 +36,7 @@ var (
|
||||
//
|
||||
// TODO(roasbeef): move inmpl to main package?
|
||||
type databaseChannelGraph struct {
|
||||
db *channeldb.ChannelGraph
|
||||
db *graphdb.ChannelGraph
|
||||
}
|
||||
|
||||
// A compile time assertion to ensure databaseChannelGraph meets the
|
||||
@ -44,7 +45,7 @@ var _ ChannelGraph = (*databaseChannelGraph)(nil)
|
||||
|
||||
// ChannelGraphFromDatabase returns an instance of the autopilot.ChannelGraph
|
||||
// backed by a live, open channeldb instance.
|
||||
func ChannelGraphFromDatabase(db *channeldb.ChannelGraph) ChannelGraph {
|
||||
func ChannelGraphFromDatabase(db *graphdb.ChannelGraph) ChannelGraph {
|
||||
return &databaseChannelGraph{
|
||||
db: db,
|
||||
}
|
||||
@ -54,11 +55,11 @@ func ChannelGraphFromDatabase(db *channeldb.ChannelGraph) ChannelGraph {
|
||||
// channeldb.LightningNode. The wrapper method implement the autopilot.Node
|
||||
// interface.
|
||||
type dbNode struct {
|
||||
db *channeldb.ChannelGraph
|
||||
db *graphdb.ChannelGraph
|
||||
|
||||
tx kvdb.RTx
|
||||
|
||||
node *channeldb.LightningNode
|
||||
node *models.LightningNode
|
||||
}
|
||||
|
||||
// A compile time assertion to ensure dbNode meets the autopilot.Node
|
||||
@ -134,7 +135,9 @@ func (d *dbNode) ForEachChannel(cb func(ChannelEdge) error) error {
|
||||
//
|
||||
// NOTE: Part of the autopilot.ChannelGraph interface.
|
||||
func (d *databaseChannelGraph) ForEachNode(cb func(Node) error) error {
|
||||
return d.db.ForEachNode(func(tx kvdb.RTx, n *channeldb.LightningNode) error {
|
||||
return d.db.ForEachNode(func(tx kvdb.RTx,
|
||||
n *models.LightningNode) error {
|
||||
|
||||
// We'll skip over any node that doesn't have any advertised
|
||||
// addresses. As we won't be able to reach them to actually
|
||||
// open any channels.
|
||||
@ -157,7 +160,7 @@ func (d *databaseChannelGraph) ForEachNode(cb func(Node) error) error {
|
||||
func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
|
||||
capacity btcutil.Amount) (*ChannelEdge, *ChannelEdge, error) {
|
||||
|
||||
fetchNode := func(pub *btcec.PublicKey) (*channeldb.LightningNode, error) {
|
||||
fetchNode := func(pub *btcec.PublicKey) (*models.LightningNode, error) {
|
||||
if pub != nil {
|
||||
vertex, err := route.NewVertexFromBytes(
|
||||
pub.SerializeCompressed(),
|
||||
@ -168,10 +171,10 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
|
||||
|
||||
dbNode, err := d.db.FetchLightningNode(vertex)
|
||||
switch {
|
||||
case err == channeldb.ErrGraphNodeNotFound:
|
||||
case errors.Is(err, graphdb.ErrGraphNodeNotFound):
|
||||
fallthrough
|
||||
case err == channeldb.ErrGraphNotFound:
|
||||
graphNode := &channeldb.LightningNode{
|
||||
case errors.Is(err, graphdb.ErrGraphNotFound):
|
||||
graphNode := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
Addresses: []net.Addr{
|
||||
&net.TCPAddr{
|
||||
@ -198,7 +201,7 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbNode := &channeldb.LightningNode{
|
||||
dbNode := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
Addresses: []net.Addr{
|
||||
&net.TCPAddr{
|
||||
@ -302,7 +305,7 @@ func (d *databaseChannelGraph) addRandNode() (*btcec.PublicKey, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbNode := &channeldb.LightningNode{
|
||||
dbNode := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
Addresses: []net.Addr{
|
||||
&net.TCPAddr{
|
||||
@ -478,7 +481,7 @@ func (m *memChannelGraph) addRandNode() (*btcec.PublicKey, error) {
|
||||
// databaseChannelGraphCached wraps a channeldb.ChannelGraph instance with the
|
||||
// necessary API to properly implement the autopilot.ChannelGraph interface.
|
||||
type databaseChannelGraphCached struct {
|
||||
db *channeldb.ChannelGraph
|
||||
db *graphdb.ChannelGraph
|
||||
}
|
||||
|
||||
// A compile time assertion to ensure databaseChannelGraphCached meets the
|
||||
@ -487,7 +490,7 @@ var _ ChannelGraph = (*databaseChannelGraphCached)(nil)
|
||||
|
||||
// ChannelGraphFromCachedDatabase returns an instance of the
|
||||
// autopilot.ChannelGraph backed by a live, open channeldb instance.
|
||||
func ChannelGraphFromCachedDatabase(db *channeldb.ChannelGraph) ChannelGraph {
|
||||
func ChannelGraphFromCachedDatabase(db *graphdb.ChannelGraph) ChannelGraph {
|
||||
return &databaseChannelGraphCached{
|
||||
db: db,
|
||||
}
|
||||
@ -498,7 +501,7 @@ func ChannelGraphFromCachedDatabase(db *channeldb.ChannelGraph) ChannelGraph {
|
||||
// interface.
|
||||
type dbNodeCached struct {
|
||||
node route.Vertex
|
||||
channels map[uint64]*channeldb.DirectedChannel
|
||||
channels map[uint64]*graphdb.DirectedChannel
|
||||
}
|
||||
|
||||
// A compile time assertion to ensure dbNodeCached meets the autopilot.Node
|
||||
@ -552,7 +555,7 @@ func (nc dbNodeCached) ForEachChannel(cb func(ChannelEdge) error) error {
|
||||
// NOTE: Part of the autopilot.ChannelGraph interface.
|
||||
func (dc *databaseChannelGraphCached) ForEachNode(cb func(Node) error) error {
|
||||
return dc.db.ForEachNodeCached(func(n route.Vertex,
|
||||
channels map[uint64]*channeldb.DirectedChannel) error {
|
||||
channels map[uint64]*graphdb.DirectedChannel) error {
|
||||
|
||||
if len(channels) > 0 {
|
||||
node := dbNodeCached{
|
||||
|
@ -8,7 +8,8 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -24,17 +25,21 @@ type testGraph interface {
|
||||
}
|
||||
|
||||
func newDiskChanGraph(t *testing.T) (testGraph, error) {
|
||||
// Next, create channeldb for the first time.
|
||||
cdb, err := channeldb.Open(t.TempDir())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, cdb.Close())
|
||||
backend, err := kvdb.GetBoltBackend(&kvdb.BoltBackendConfig{
|
||||
DBPath: t.TempDir(),
|
||||
DBFileName: "graph.db",
|
||||
NoFreelistSync: true,
|
||||
AutoCompact: false,
|
||||
AutoCompactMinAge: kvdb.DefaultBoltAutoCompactMinAge,
|
||||
DBTimeout: kvdb.DefaultDBTimeout,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
graphDB, err := graphdb.NewChannelGraph(backend)
|
||||
require.NoError(t, err)
|
||||
|
||||
return &databaseChannelGraph{
|
||||
db: cdb.ChannelGraph(),
|
||||
db: graphDB,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -37,11 +37,7 @@ var (
|
||||
func initHintCache(t *testing.T) *channeldb.HeightHintCache {
|
||||
t.Helper()
|
||||
|
||||
db, err := channeldb.Open(t.TempDir())
|
||||
require.NoError(t, err, "unable to create db")
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, db.Close())
|
||||
})
|
||||
db := channeldb.OpenForTesting(t, t.TempDir())
|
||||
|
||||
testCfg := channeldb.CacheConfig{
|
||||
QueryDisable: false,
|
||||
|
@ -33,11 +33,7 @@ var (
|
||||
func initHintCache(t *testing.T) *channeldb.HeightHintCache {
|
||||
t.Helper()
|
||||
|
||||
db, err := channeldb.Open(t.TempDir())
|
||||
require.NoError(t, err, "unable to create db")
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, db.Close())
|
||||
})
|
||||
db := channeldb.OpenForTesting(t, t.TempDir())
|
||||
|
||||
testCfg := channeldb.CacheConfig{
|
||||
QueryDisable: false,
|
||||
|
@ -1906,10 +1906,8 @@ func TestInterfaces(t *testing.T, targetBackEnd string) {
|
||||
|
||||
// Initialize a height hint cache for each notifier.
|
||||
tempDir := t.TempDir()
|
||||
db, err := channeldb.Open(tempDir)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create db: %v", err)
|
||||
}
|
||||
db := channeldb.OpenForTesting(t, tempDir)
|
||||
|
||||
testCfg := channeldb.CacheConfig{
|
||||
QueryDisable: false,
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ import (
|
||||
"github.com/lightningnetwork/lnd/chainntnfs/btcdnotify"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs/neutrinonotify"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"github.com/btcsuite/btcwallet/chain"
|
||||
"github.com/btcsuite/btcwallet/waddrmgr"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/routing/chainview"
|
||||
)
|
||||
@ -94,7 +94,7 @@ func (n *NoChainBackend) DisconnectedBlocks() <-chan *chainview.FilteredBlock {
|
||||
return make(chan *chainview.FilteredBlock)
|
||||
}
|
||||
|
||||
func (n *NoChainBackend) UpdateFilter([]channeldb.EdgePoint, uint32) error {
|
||||
func (n *NoChainBackend) UpdateFilter([]graphdb.EdgePoint, uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,10 @@ package chanbackup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
)
|
||||
|
||||
// LiveChannelSource is an interface that allows us to query for the set of
|
||||
@ -20,23 +17,14 @@ type LiveChannelSource interface {
|
||||
|
||||
// FetchChannel attempts to locate a live channel identified by the
|
||||
// passed chanPoint. Optionally an existing db tx can be supplied.
|
||||
FetchChannel(tx kvdb.RTx, chanPoint wire.OutPoint) (
|
||||
*channeldb.OpenChannel, error)
|
||||
}
|
||||
|
||||
// AddressSource is an interface that allows us to query for the set of
|
||||
// addresses a node can be connected to.
|
||||
type AddressSource interface {
|
||||
// AddrsForNode returns all known addresses for the target node public
|
||||
// key.
|
||||
AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error)
|
||||
FetchChannel(chanPoint wire.OutPoint) (*channeldb.OpenChannel, error)
|
||||
}
|
||||
|
||||
// assembleChanBackup attempts to assemble a static channel backup for the
|
||||
// passed open channel. The backup includes all information required to restore
|
||||
// the channel, as well as addressing information so we can find the peer and
|
||||
// reconnect to them to initiate the protocol.
|
||||
func assembleChanBackup(addrSource AddressSource,
|
||||
func assembleChanBackup(addrSource channeldb.AddrSource,
|
||||
openChan *channeldb.OpenChannel) (*Single, error) {
|
||||
|
||||
log.Debugf("Crafting backup for ChannelPoint(%v)",
|
||||
@ -44,10 +32,13 @@ func assembleChanBackup(addrSource AddressSource,
|
||||
|
||||
// First, we'll query the channel source to obtain all the addresses
|
||||
// that are associated with the peer for this channel.
|
||||
nodeAddrs, err := addrSource.AddrsForNode(openChan.IdentityPub)
|
||||
known, nodeAddrs, err := addrSource.AddrsForNode(openChan.IdentityPub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !known {
|
||||
return nil, fmt.Errorf("node unknown by address source")
|
||||
}
|
||||
|
||||
single := NewSingle(openChan, nodeAddrs)
|
||||
|
||||
@ -100,11 +91,11 @@ func buildCloseTxInputs(
|
||||
// the target channel identified by its channel point. If we're unable to find
|
||||
// the target channel, then an error will be returned.
|
||||
func FetchBackupForChan(chanPoint wire.OutPoint, chanSource LiveChannelSource,
|
||||
addrSource AddressSource) (*Single, error) {
|
||||
addrSource channeldb.AddrSource) (*Single, error) {
|
||||
|
||||
// First, we'll query the channel source to see if the channel is known
|
||||
// and open within the database.
|
||||
targetChan, err := chanSource.FetchChannel(nil, chanPoint)
|
||||
targetChan, err := chanSource.FetchChannel(chanPoint)
|
||||
if err != nil {
|
||||
// If we can't find the channel, then we return with an error,
|
||||
// as we have nothing to backup.
|
||||
@ -124,7 +115,7 @@ func FetchBackupForChan(chanPoint wire.OutPoint, chanSource LiveChannelSource,
|
||||
// FetchStaticChanBackups will return a plaintext static channel back up for
|
||||
// all known active/open channels within the passed channel source.
|
||||
func FetchStaticChanBackups(chanSource LiveChannelSource,
|
||||
addrSource AddressSource) ([]Single, error) {
|
||||
addrSource channeldb.AddrSource) ([]Single, error) {
|
||||
|
||||
// First, we'll query the backup source for information concerning all
|
||||
// currently open and available channels.
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -40,7 +39,7 @@ func (m *mockChannelSource) FetchAllChannels() ([]*channeldb.OpenChannel, error)
|
||||
return chans, nil
|
||||
}
|
||||
|
||||
func (m *mockChannelSource) FetchChannel(_ kvdb.RTx, chanPoint wire.OutPoint) (
|
||||
func (m *mockChannelSource) FetchChannel(chanPoint wire.OutPoint) (
|
||||
*channeldb.OpenChannel, error) {
|
||||
|
||||
if m.failQuery {
|
||||
@ -62,20 +61,19 @@ func (m *mockChannelSource) addAddrsForNode(nodePub *btcec.PublicKey, addrs []ne
|
||||
m.addrs[nodeKey] = addrs
|
||||
}
|
||||
|
||||
func (m *mockChannelSource) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error) {
|
||||
func (m *mockChannelSource) AddrsForNode(nodePub *btcec.PublicKey) (bool,
|
||||
[]net.Addr, error) {
|
||||
|
||||
if m.failQuery {
|
||||
return nil, fmt.Errorf("fail")
|
||||
return false, nil, fmt.Errorf("fail")
|
||||
}
|
||||
|
||||
var nodeKey [33]byte
|
||||
copy(nodeKey[:], nodePub.SerializeCompressed())
|
||||
|
||||
addrs, ok := m.addrs[nodeKey]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("can't find addr")
|
||||
}
|
||||
|
||||
return addrs, nil
|
||||
return ok, addrs, nil
|
||||
}
|
||||
|
||||
// TestFetchBackupForChan tests that we're able to construct a single channel
|
||||
|
@ -2,24 +2,13 @@ package lnd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/chanbackup"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channelnotifier"
|
||||
)
|
||||
|
||||
// addrSource is an interface that allow us to get the addresses for a target
|
||||
// node. We'll need this in order to be able to properly proxy the
|
||||
// notifications to create SCBs.
|
||||
type addrSource interface {
|
||||
// AddrsForNode returns all known addresses for the target node public
|
||||
// key.
|
||||
AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error)
|
||||
}
|
||||
|
||||
// channelNotifier is an implementation of the chanbackup.ChannelNotifier
|
||||
// interface using the existing channelnotifier.ChannelNotifier struct. This
|
||||
// implementation allows us to satisfy all the dependencies of the
|
||||
@ -32,7 +21,7 @@ type channelNotifier struct {
|
||||
// addrs is an implementation of the addrSource interface that allows
|
||||
// us to get the latest set of addresses for a given node. We'll need
|
||||
// this to be able to create an SCB for new channels.
|
||||
addrs addrSource
|
||||
addrs channeldb.AddrSource
|
||||
}
|
||||
|
||||
// SubscribeChans requests a new channel subscription relative to the initial
|
||||
@ -56,7 +45,7 @@ func (c *channelNotifier) SubscribeChans(startingChans map[wire.OutPoint]struct{
|
||||
// chanUpdates channel to inform subscribers about new pending or
|
||||
// confirmed channels.
|
||||
sendChanOpenUpdate := func(newOrPendingChan *channeldb.OpenChannel) {
|
||||
nodeAddrs, err := c.addrs.AddrsForNode(
|
||||
_, nodeAddrs, err := c.addrs.AddrsForNode(
|
||||
newOrPendingChan.IdentityPub,
|
||||
)
|
||||
if err != nil {
|
||||
|
83
channeldb/addr_source.go
Normal file
83
channeldb/addr_source.go
Normal file
@ -0,0 +1,83 @@
|
||||
package channeldb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
)
|
||||
|
||||
// AddrSource is an interface that allow us to get the addresses for a target
|
||||
// node. It may combine the results of multiple address sources.
|
||||
type AddrSource interface {
|
||||
// AddrsForNode returns all known addresses for the target node public
|
||||
// key. The returned boolean must indicate if the given node is unknown
|
||||
// to the backing source.
|
||||
AddrsForNode(nodePub *btcec.PublicKey) (bool, []net.Addr, error)
|
||||
}
|
||||
|
||||
// multiAddrSource is an implementation of AddrSource which gathers all the
|
||||
// known addresses for a given node from multiple backends and de-duplicates the
|
||||
// results.
|
||||
type multiAddrSource struct {
|
||||
sources []AddrSource
|
||||
}
|
||||
|
||||
// NewMultiAddrSource constructs a new AddrSource which will query all the
|
||||
// provided sources for a node's addresses and will then de-duplicate the
|
||||
// results.
|
||||
func NewMultiAddrSource(sources ...AddrSource) AddrSource {
|
||||
return &multiAddrSource{
|
||||
sources: sources,
|
||||
}
|
||||
}
|
||||
|
||||
// AddrsForNode returns all known addresses for the target node public key. It
|
||||
// queries all the address sources provided and de-duplicates the results. The
|
||||
// returned boolean is false only if none of the backing sources know of the
|
||||
// node.
|
||||
//
|
||||
// NOTE: this implements the AddrSource interface.
|
||||
func (c *multiAddrSource) AddrsForNode(nodePub *btcec.PublicKey) (bool,
|
||||
[]net.Addr, error) {
|
||||
|
||||
if len(c.sources) == 0 {
|
||||
return false, nil, errors.New("no address sources")
|
||||
}
|
||||
|
||||
// The multiple address sources will likely contain duplicate addresses,
|
||||
// so we use a map here to de-dup them.
|
||||
dedupedAddrs := make(map[string]net.Addr)
|
||||
|
||||
// known will be set to true if any backing source is aware of the node.
|
||||
var known bool
|
||||
|
||||
// Iterate over all the address sources and query each one for the
|
||||
// addresses it has for the node in question.
|
||||
for _, src := range c.sources {
|
||||
isKnown, addrs, err := src.AddrsForNode(nodePub)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
if isKnown {
|
||||
known = true
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
dedupedAddrs[addr.String()] = addr
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the map into a list we can return.
|
||||
addrs := make([]net.Addr, 0, len(dedupedAddrs))
|
||||
for _, addr := range dedupedAddrs {
|
||||
addrs = append(addrs, addr)
|
||||
}
|
||||
|
||||
return known, addrs, nil
|
||||
}
|
||||
|
||||
// A compile-time check to ensure that multiAddrSource implements the AddrSource
|
||||
// interface.
|
||||
var _ AddrSource = (*multiAddrSource)(nil)
|
149
channeldb/addr_source_test.go
Normal file
149
channeldb/addr_source_test.go
Normal file
@ -0,0 +1,149 @@
|
||||
package channeldb
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
addr1 = &net.TCPAddr{IP: (net.IP)([]byte{0x1}), Port: 1}
|
||||
addr2 = &net.TCPAddr{IP: (net.IP)([]byte{0x2}), Port: 2}
|
||||
addr3 = &net.TCPAddr{IP: (net.IP)([]byte{0x3}), Port: 3}
|
||||
)
|
||||
|
||||
// TestMultiAddrSource tests that the multiAddrSource correctly merges and
|
||||
// deduplicates the results of a set of AddrSource implementations.
|
||||
func TestMultiAddrSource(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var pk1 = newTestPubKey(t)
|
||||
|
||||
t.Run("both sources have results", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var (
|
||||
src1 = newMockAddrSource(t)
|
||||
src2 = newMockAddrSource(t)
|
||||
)
|
||||
t.Cleanup(func() {
|
||||
src1.AssertExpectations(t)
|
||||
src2.AssertExpectations(t)
|
||||
})
|
||||
|
||||
// Let source 1 know of 2 addresses (addr 1 and 2) for node 1.
|
||||
src1.On("AddrsForNode", pk1).Return(
|
||||
true, []net.Addr{addr1, addr2}, nil,
|
||||
).Once()
|
||||
|
||||
// Let source 2 know of 2 addresses (addr 2 and 3) for node 1.
|
||||
src2.On("AddrsForNode", pk1).Return(
|
||||
true, []net.Addr{addr2, addr3}, nil,
|
||||
[]net.Addr{addr2, addr3}, nil,
|
||||
).Once()
|
||||
|
||||
// Create a multi-addr source that consists of both source 1
|
||||
// and 2.
|
||||
multiSrc := NewMultiAddrSource(src1, src2)
|
||||
|
||||
// Query it for the addresses known for node 1. The results
|
||||
// should contain addr 1, 2 and 3.
|
||||
known, addrs, err := multiSrc.AddrsForNode(pk1)
|
||||
require.NoError(t, err)
|
||||
require.True(t, known)
|
||||
require.ElementsMatch(t, addrs, []net.Addr{addr1, addr2, addr3})
|
||||
})
|
||||
|
||||
t.Run("only once source has results", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var (
|
||||
src1 = newMockAddrSource(t)
|
||||
src2 = newMockAddrSource(t)
|
||||
)
|
||||
t.Cleanup(func() {
|
||||
src1.AssertExpectations(t)
|
||||
src2.AssertExpectations(t)
|
||||
})
|
||||
|
||||
// Let source 1 know of address 1 for node 1.
|
||||
src1.On("AddrsForNode", pk1).Return(
|
||||
true, []net.Addr{addr1}, nil,
|
||||
).Once()
|
||||
src2.On("AddrsForNode", pk1).Return(false, nil, nil).Once()
|
||||
|
||||
// Create a multi-addr source that consists of both source 1
|
||||
// and 2.
|
||||
multiSrc := NewMultiAddrSource(src1, src2)
|
||||
|
||||
// Query it for the addresses known for node 1. The results
|
||||
// should contain addr 1.
|
||||
known, addrs, err := multiSrc.AddrsForNode(pk1)
|
||||
require.NoError(t, err)
|
||||
require.True(t, known)
|
||||
require.ElementsMatch(t, addrs, []net.Addr{addr1})
|
||||
})
|
||||
|
||||
t.Run("unknown address", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var (
|
||||
src1 = newMockAddrSource(t)
|
||||
src2 = newMockAddrSource(t)
|
||||
)
|
||||
t.Cleanup(func() {
|
||||
src1.AssertExpectations(t)
|
||||
src2.AssertExpectations(t)
|
||||
})
|
||||
|
||||
// Create a multi-addr source that consists of both source 1
|
||||
// and 2. Neither source known of node 1.
|
||||
multiSrc := NewMultiAddrSource(src1, src2)
|
||||
|
||||
src1.On("AddrsForNode", pk1).Return(false, nil, nil).Once()
|
||||
src2.On("AddrsForNode", pk1).Return(false, nil, nil).Once()
|
||||
|
||||
// Query it for the addresses known for node 1. It should return
|
||||
// false to indicate that the node is unknown to all backing
|
||||
// sources.
|
||||
known, addrs, err := multiSrc.AddrsForNode(pk1)
|
||||
require.NoError(t, err)
|
||||
require.False(t, known)
|
||||
require.Empty(t, addrs)
|
||||
})
|
||||
}
|
||||
|
||||
type mockAddrSource struct {
|
||||
t *testing.T
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
var _ AddrSource = (*mockAddrSource)(nil)
|
||||
|
||||
func newMockAddrSource(t *testing.T) *mockAddrSource {
|
||||
return &mockAddrSource{t: t}
|
||||
}
|
||||
|
||||
func (m *mockAddrSource) AddrsForNode(pub *btcec.PublicKey) (bool, []net.Addr,
|
||||
error) {
|
||||
|
||||
args := m.Called(pub)
|
||||
if args.Get(1) == nil {
|
||||
return args.Bool(0), nil, args.Error(2)
|
||||
}
|
||||
|
||||
addrs, ok := args.Get(1).([]net.Addr)
|
||||
require.True(m.t, ok)
|
||||
|
||||
return args.Bool(0), addrs, args.Error(2)
|
||||
}
|
||||
|
||||
func newTestPubKey(t *testing.T) *btcec.PublicKey {
|
||||
priv, err := btcec.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
return priv.PubKey()
|
||||
}
|
@ -19,8 +19,9 @@ import (
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcwallet/walletdb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
@ -1330,7 +1331,7 @@ func fetchChanBucket(tx kvdb.RTx, nodeKey *btcec.PublicKey,
|
||||
// With the bucket for the node and chain fetched, we can now go down
|
||||
// another level, for this channel itself.
|
||||
var chanPointBuf bytes.Buffer
|
||||
if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chanBucket := chainBucket.NestedReadBucket(chanPointBuf.Bytes())
|
||||
@ -1377,7 +1378,7 @@ func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey,
|
||||
// With the bucket for the node and chain fetched, we can now go down
|
||||
// another level, for this channel itself.
|
||||
var chanPointBuf bytes.Buffer
|
||||
if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chanBucket := chainBucket.NestedReadWriteBucket(chanPointBuf.Bytes())
|
||||
@ -1422,7 +1423,8 @@ func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
|
||||
}
|
||||
|
||||
var chanPointBuf bytes.Buffer
|
||||
if err := writeOutpoint(&chanPointBuf, &c.FundingOutpoint); err != nil {
|
||||
err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -3822,7 +3824,7 @@ func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary,
|
||||
}
|
||||
|
||||
var chanPointBuf bytes.Buffer
|
||||
err := writeOutpoint(&chanPointBuf, &c.FundingOutpoint)
|
||||
err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package channeldb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"math/rand"
|
||||
"net"
|
||||
"reflect"
|
||||
@ -10,20 +11,22 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
_ "github.com/btcsuite/btcwallet/walletdb/bdb"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnmock"
|
||||
"github.com/lightningnetwork/lnd/lntest/channels"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
"github.com/lightningnetwork/lnd/shachain"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -43,8 +46,20 @@ var (
|
||||
}
|
||||
privKey, pubKey = btcec.PrivKeyFromBytes(key[:])
|
||||
|
||||
testRBytes, _ = hex.DecodeString("8ce2bc69281ce27da07e6683571319d18e" +
|
||||
"949ddfa2965fb6caa1bf0314f882d7")
|
||||
testSBytes, _ = hex.DecodeString("299105481d63e0f4bc2a88121167221b67" +
|
||||
"00d72a0ead154c03be696a292d24ae")
|
||||
testRScalar = new(btcec.ModNScalar)
|
||||
testSScalar = new(btcec.ModNScalar)
|
||||
_ = testRScalar.SetByteSlice(testRBytes)
|
||||
_ = testSScalar.SetByteSlice(testSBytes)
|
||||
testSig = ecdsa.NewSignature(testRScalar, testSScalar)
|
||||
|
||||
wireSig, _ = lnwire.NewSigFromSignature(testSig)
|
||||
|
||||
testPub = route.Vertex{2, 202, 4}
|
||||
|
||||
testClock = clock.NewTestClock(testNow)
|
||||
|
||||
// defaultPendingHeight is the default height at which we set
|
||||
|
@ -11,38 +11,13 @@ import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/shachain"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
)
|
||||
|
||||
// writeOutpoint writes an outpoint to the passed writer using the minimal
|
||||
// amount of bytes possible.
|
||||
func writeOutpoint(w io.Writer, o *wire.OutPoint) error {
|
||||
if _, err := w.Write(o.Hash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(w, byteOrder, o.Index); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// readOutpoint reads an outpoint from the passed reader that was previously
|
||||
// written using the writeOutpoint struct.
|
||||
func readOutpoint(r io.Reader, o *wire.OutPoint) error {
|
||||
if _, err := io.ReadFull(r, o.Hash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(r, byteOrder, &o.Index); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnknownElementType is an error returned when the codec is unable to encode or
|
||||
// decode a particular type.
|
||||
type UnknownElementType struct {
|
||||
@ -98,7 +73,7 @@ func WriteElement(w io.Writer, element interface{}) error {
|
||||
}
|
||||
|
||||
case wire.OutPoint:
|
||||
return writeOutpoint(w, &e)
|
||||
return graphdb.WriteOutpoint(w, &e)
|
||||
|
||||
case lnwire.ShortChannelID:
|
||||
if err := binary.Write(w, byteOrder, e.ToUint64()); err != nil {
|
||||
@ -218,7 +193,7 @@ func WriteElement(w io.Writer, element interface{}) error {
|
||||
}
|
||||
|
||||
case net.Addr:
|
||||
if err := serializeAddr(w, e); err != nil {
|
||||
if err := graphdb.SerializeAddr(w, e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -228,7 +203,7 @@ func WriteElement(w io.Writer, element interface{}) error {
|
||||
}
|
||||
|
||||
for _, addr := range e {
|
||||
if err := serializeAddr(w, addr); err != nil {
|
||||
if err := graphdb.SerializeAddr(w, addr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -288,7 +263,7 @@ func ReadElement(r io.Reader, element interface{}) error {
|
||||
}
|
||||
|
||||
case *wire.OutPoint:
|
||||
return readOutpoint(r, e)
|
||||
return graphdb.ReadOutpoint(r, e)
|
||||
|
||||
case *lnwire.ShortChannelID:
|
||||
var a uint64
|
||||
@ -451,7 +426,7 @@ func ReadElement(r io.Reader, element interface{}) error {
|
||||
}
|
||||
|
||||
case *net.Addr:
|
||||
addr, err := deserializeAddr(r)
|
||||
addr, err := graphdb.DeserializeAddr(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -465,7 +440,7 @@ func ReadElement(r io.Reader, element interface{}) error {
|
||||
|
||||
*e = make([]net.Addr, numAddrs)
|
||||
for i := uint32(0); i < numAddrs; i++ {
|
||||
addr, err := deserializeAddr(r)
|
||||
addr, err := graphdb.DeserializeAddr(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
144
channeldb/db.go
144
channeldb/db.go
@ -30,10 +30,11 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration33"
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration_01_to_11"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -335,7 +336,6 @@ type DB struct {
|
||||
channelStateDB *ChannelStateDB
|
||||
|
||||
dbPath string
|
||||
graph *ChannelGraph
|
||||
clock clock.Clock
|
||||
dryRun bool
|
||||
keepFailedPaymentAttempts bool
|
||||
@ -346,38 +346,37 @@ type DB struct {
|
||||
noRevLogAmtData bool
|
||||
}
|
||||
|
||||
// Open opens or creates channeldb. Any necessary schemas migrations due
|
||||
// to updates will take place as necessary.
|
||||
// TODO(bhandras): deprecate this function.
|
||||
func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) {
|
||||
opts := DefaultOptions()
|
||||
for _, modifier := range modifiers {
|
||||
modifier(&opts)
|
||||
}
|
||||
// OpenForTesting opens or creates a channeldb to be used for tests. Any
|
||||
// necessary schemas migrations due to updates will take place as necessary.
|
||||
func OpenForTesting(t testing.TB, dbPath string,
|
||||
modifiers ...OptionModifier) *DB {
|
||||
|
||||
backend, err := kvdb.GetBoltBackend(&kvdb.BoltBackendConfig{
|
||||
DBPath: dbPath,
|
||||
DBFileName: dbName,
|
||||
NoFreelistSync: opts.NoFreelistSync,
|
||||
AutoCompact: opts.AutoCompact,
|
||||
AutoCompactMinAge: opts.AutoCompactMinAge,
|
||||
DBTimeout: opts.DBTimeout,
|
||||
NoFreelistSync: true,
|
||||
AutoCompact: false,
|
||||
AutoCompactMinAge: kvdb.DefaultBoltAutoCompactMinAge,
|
||||
DBTimeout: kvdb.DefaultDBTimeout,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
db, err := CreateWithBackend(backend, modifiers...)
|
||||
if err == nil {
|
||||
db.dbPath = dbPath
|
||||
}
|
||||
return db, err
|
||||
require.NoError(t, err)
|
||||
|
||||
db.dbPath = dbPath
|
||||
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, db.Close())
|
||||
})
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
// CreateWithBackend creates channeldb instance using the passed kvdb.Backend.
|
||||
// Any necessary schemas migrations due to updates will take place as necessary.
|
||||
func CreateWithBackend(backend kvdb.Backend,
|
||||
modifiers ...OptionModifier) (*DB, error) {
|
||||
func CreateWithBackend(backend kvdb.Backend, modifiers ...OptionModifier) (*DB,
|
||||
error) {
|
||||
|
||||
opts := DefaultOptions()
|
||||
for _, modifier := range modifiers {
|
||||
@ -408,16 +407,6 @@ func CreateWithBackend(backend kvdb.Backend,
|
||||
// Set the parent pointer (only used in tests).
|
||||
chanDB.channelStateDB.parent = chanDB
|
||||
|
||||
var err error
|
||||
chanDB.graph, err = NewChannelGraph(
|
||||
backend, opts.RejectCacheSize, opts.ChannelCacheSize,
|
||||
opts.BatchCommitInterval, opts.PreAllocCacheNumNodes,
|
||||
opts.UseGraphCache, opts.NoMigration,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Synchronize the version of database and apply migrations if needed.
|
||||
if !opts.NoMigration {
|
||||
if err := chanDB.syncVersions(dbVersions); err != nil {
|
||||
@ -646,7 +635,9 @@ func (c *ChannelStateDB) fetchNodeChannels(chainBucket kvdb.RBucket) (
|
||||
chanBucket := chainBucket.NestedReadBucket(chanPoint)
|
||||
|
||||
var outPoint wire.OutPoint
|
||||
err := readOutpoint(bytes.NewReader(chanPoint), &outPoint)
|
||||
err := graphdb.ReadOutpoint(
|
||||
bytes.NewReader(chanPoint), &outPoint,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -670,12 +661,12 @@ func (c *ChannelStateDB) fetchNodeChannels(chainBucket kvdb.RBucket) (
|
||||
|
||||
// FetchChannel attempts to locate a channel specified by the passed channel
|
||||
// point. If the channel cannot be found, then an error will be returned.
|
||||
// Optionally an existing db tx can be supplied.
|
||||
func (c *ChannelStateDB) FetchChannel(tx kvdb.RTx, chanPoint wire.OutPoint) (
|
||||
*OpenChannel, error) {
|
||||
func (c *ChannelStateDB) FetchChannel(chanPoint wire.OutPoint) (*OpenChannel,
|
||||
error) {
|
||||
|
||||
var targetChanPoint bytes.Buffer
|
||||
if err := writeOutpoint(&targetChanPoint, &chanPoint); err != nil {
|
||||
err := graphdb.WriteOutpoint(&targetChanPoint, &chanPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -686,7 +677,7 @@ func (c *ChannelStateDB) FetchChannel(tx kvdb.RTx, chanPoint wire.OutPoint) (
|
||||
return targetChanPointBytes, &chanPoint, nil
|
||||
}
|
||||
|
||||
return c.channelScanner(tx, selector)
|
||||
return c.channelScanner(nil, selector)
|
||||
}
|
||||
|
||||
// FetchChannelByID attempts to locate a channel specified by the passed channel
|
||||
@ -709,7 +700,9 @@ func (c *ChannelStateDB) FetchChannelByID(tx kvdb.RTx, id lnwire.ChannelID) (
|
||||
)
|
||||
err := chainBkt.ForEach(func(k, _ []byte) error {
|
||||
var outPoint wire.OutPoint
|
||||
err := readOutpoint(bytes.NewReader(k), &outPoint)
|
||||
err := graphdb.ReadOutpoint(
|
||||
bytes.NewReader(k), &outPoint,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1089,7 +1082,7 @@ func (c *ChannelStateDB) FetchClosedChannel(chanID *wire.OutPoint) (
|
||||
|
||||
var b bytes.Buffer
|
||||
var err error
|
||||
if err = writeOutpoint(&b, chanID); err != nil {
|
||||
if err = graphdb.WriteOutpoint(&b, chanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1131,7 +1124,9 @@ func (c *ChannelStateDB) FetchClosedChannelForID(cid lnwire.ChannelID) (
|
||||
// We scan over all possible candidates for this channel ID.
|
||||
for ; op != nil && bytes.Compare(cid[:30], op[:30]) <= 0; op, c = cursor.Next() {
|
||||
var outPoint wire.OutPoint
|
||||
err := readOutpoint(bytes.NewReader(op), &outPoint)
|
||||
err := graphdb.ReadOutpoint(
|
||||
bytes.NewReader(op), &outPoint,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1173,7 +1168,7 @@ func (c *ChannelStateDB) MarkChanFullyClosed(chanPoint *wire.OutPoint) error {
|
||||
)
|
||||
err := kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
|
||||
var b bytes.Buffer
|
||||
if err := writeOutpoint(&b, chanPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&b, chanPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1344,48 +1339,24 @@ func (c *ChannelStateDB) RestoreChannelShells(channelShells ...*ChannelShell) er
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddrsForNode consults the graph and channel database for all addresses known
|
||||
// to the passed node public key.
|
||||
func (d *DB) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr,
|
||||
error) {
|
||||
|
||||
// AddrsForNode consults the channel database for all addresses known to the
|
||||
// passed node public key. The returned boolean indicates if the given node is
|
||||
// unknown to the channel DB or not.
|
||||
//
|
||||
// NOTE: this is part of the AddrSource interface.
|
||||
func (d *DB) AddrsForNode(nodePub *btcec.PublicKey) (bool, []net.Addr, error) {
|
||||
linkNode, err := d.channelStateDB.linkNodeDB.FetchLinkNode(nodePub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Only if the error is something other than ErrNodeNotFound do we
|
||||
// return it.
|
||||
switch {
|
||||
case err != nil && !errors.Is(err, ErrNodeNotFound):
|
||||
return false, nil, err
|
||||
|
||||
case errors.Is(err, ErrNodeNotFound):
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
// We'll also query the graph for this peer to see if they have any
|
||||
// addresses that we don't currently have stored within the link node
|
||||
// database.
|
||||
pubKey, err := route.NewVertexFromBytes(nodePub.SerializeCompressed())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
graphNode, err := d.graph.FetchLightningNode(pubKey)
|
||||
if err != nil && err != ErrGraphNodeNotFound {
|
||||
return nil, err
|
||||
} else if err == ErrGraphNodeNotFound {
|
||||
// If the node isn't found, then that's OK, as we still have the
|
||||
// link node data. But any other error needs to be returned.
|
||||
graphNode = &LightningNode{}
|
||||
}
|
||||
|
||||
// Now that we have both sources of addrs for this node, we'll use a
|
||||
// map to de-duplicate any addresses between the two sources, and
|
||||
// produce a final list of the combined addrs.
|
||||
addrs := make(map[string]net.Addr)
|
||||
for _, addr := range linkNode.Addresses {
|
||||
addrs[addr.String()] = addr
|
||||
}
|
||||
for _, addr := range graphNode.Addresses {
|
||||
addrs[addr.String()] = addr
|
||||
}
|
||||
dedupedAddrs := make([]net.Addr, 0, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
dedupedAddrs = append(dedupedAddrs, addr)
|
||||
}
|
||||
|
||||
return dedupedAddrs, nil
|
||||
return true, linkNode.Addresses, nil
|
||||
}
|
||||
|
||||
// AbandonChannel attempts to remove the target channel from the open channel
|
||||
@ -1398,7 +1369,7 @@ func (c *ChannelStateDB) AbandonChannel(chanPoint *wire.OutPoint,
|
||||
// With the chanPoint constructed, we'll attempt to find the target
|
||||
// channel in the database. If we can't find the channel, then we'll
|
||||
// return the error back to the caller.
|
||||
dbChan, err := c.FetchChannel(nil, *chanPoint)
|
||||
dbChan, err := c.FetchChannel(*chanPoint)
|
||||
switch {
|
||||
// If the channel wasn't found, then it's possible that it was already
|
||||
// abandoned from the database.
|
||||
@ -1638,11 +1609,6 @@ func (d *DB) applyOptionalVersions(cfg OptionalMiragtionConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChannelGraph returns the current instance of the directed channel graph.
|
||||
func (d *DB) ChannelGraph() *ChannelGraph {
|
||||
return d.graph
|
||||
}
|
||||
|
||||
// ChannelStateDB returns the sub database that is concerned with the channel
|
||||
// state.
|
||||
func (d *DB) ChannelStateDB() *ChannelStateDB {
|
||||
@ -1693,7 +1659,7 @@ func fetchHistoricalChanBucket(tx kvdb.RTx,
|
||||
// With the bucket for the node and chain fetched, we can now go down
|
||||
// another level, for the channel itself.
|
||||
var chanPointBuf bytes.Buffer
|
||||
if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chanBucket := historicalChanBucket.NestedReadBucket(
|
||||
|
@ -1,17 +1,21 @@
|
||||
package channeldb
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
@ -20,6 +24,16 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
testAddr = &net.TCPAddr{IP: (net.IP)([]byte{0xA, 0x0, 0x0, 0x1}),
|
||||
Port: 9000}
|
||||
anotherAddr, _ = net.ResolveTCPAddr("tcp",
|
||||
"[2001:db8:85a3:0:0:8a2e:370:7334]:80")
|
||||
testAddrs = []net.Addr{testAddr}
|
||||
|
||||
testFeatures = lnwire.NewFeatureVector(nil, lnwire.Features)
|
||||
)
|
||||
|
||||
func TestOpenWithCreate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@ -51,11 +65,7 @@ func TestOpenWithCreate(t *testing.T) {
|
||||
|
||||
// Now, reopen the same db in dry run migration mode. Since we have not
|
||||
// applied any migrations, this should ignore the flag and not fail.
|
||||
cdb, err = Open(dbPath, OptionDryRunMigration(true))
|
||||
require.NoError(t, err, "unable to create channeldb")
|
||||
if err := cdb.Close(); err != nil {
|
||||
t.Fatalf("unable to close channeldb: %v", err)
|
||||
}
|
||||
OpenForTesting(t, dbPath, OptionDryRunMigration(true))
|
||||
}
|
||||
|
||||
// TestWipe tests that the database wipe operation completes successfully
|
||||
@ -166,25 +176,25 @@ func TestFetchClosedChannelForID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestAddrsForNode tests the we're able to properly obtain all the addresses
|
||||
// for a target node.
|
||||
func TestAddrsForNode(t *testing.T) {
|
||||
// TestMultiSourceAddrsForNode tests the we're able to properly obtain all the
|
||||
// addresses for a target node from multiple backends - in this case, the
|
||||
// channel db and graph db.
|
||||
func TestMultiSourceAddrsForNode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fullDB, err := MakeTestDB(t)
|
||||
require.NoError(t, err, "unable to make test database")
|
||||
|
||||
graph := fullDB.ChannelGraph()
|
||||
graph, err := graphdb.MakeTestGraph(t)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We'll make a test vertex to insert into the database, as the source
|
||||
// node, but this node will only have half the number of addresses it
|
||||
// usually does.
|
||||
testNode, err := createTestVertex(fullDB)
|
||||
testNode := createTestVertex(t)
|
||||
require.NoError(t, err, "unable to create test node")
|
||||
testNode.Addresses = []net.Addr{testAddr}
|
||||
if err := graph.SetSourceNode(testNode); err != nil {
|
||||
t.Fatalf("unable to set source node: %v", err)
|
||||
}
|
||||
require.NoError(t, graph.SetSourceNode(testNode))
|
||||
|
||||
// Next, we'll make a link node with the same pubkey, but with an
|
||||
// additional address.
|
||||
@ -194,28 +204,27 @@ func TestAddrsForNode(t *testing.T) {
|
||||
fullDB.channelStateDB.linkNodeDB, wire.MainNet, nodePub,
|
||||
anotherAddr,
|
||||
)
|
||||
if err := linkNode.Sync(); err != nil {
|
||||
t.Fatalf("unable to sync link node: %v", err)
|
||||
}
|
||||
require.NoError(t, linkNode.Sync())
|
||||
|
||||
// Create a multi-backend address source from the channel db and graph
|
||||
// db.
|
||||
addrSource := NewMultiAddrSource(fullDB, graph)
|
||||
|
||||
// Now that we've created a link node, as well as a vertex for the
|
||||
// node, we'll query for all its addresses.
|
||||
nodeAddrs, err := fullDB.AddrsForNode(nodePub)
|
||||
known, nodeAddrs, err := addrSource.AddrsForNode(nodePub)
|
||||
require.NoError(t, err, "unable to obtain node addrs")
|
||||
require.True(t, known)
|
||||
|
||||
expectedAddrs := make(map[string]struct{})
|
||||
expectedAddrs[testAddr.String()] = struct{}{}
|
||||
expectedAddrs[anotherAddr.String()] = struct{}{}
|
||||
|
||||
// Finally, ensure that all the expected addresses are found.
|
||||
if len(nodeAddrs) != len(expectedAddrs) {
|
||||
t.Fatalf("expected %v addrs, got %v",
|
||||
len(expectedAddrs), len(nodeAddrs))
|
||||
}
|
||||
require.Len(t, nodeAddrs, len(expectedAddrs))
|
||||
|
||||
for _, addr := range nodeAddrs {
|
||||
if _, ok := expectedAddrs[addr.String()]; !ok {
|
||||
t.Fatalf("unexpected addr: %v", addr)
|
||||
}
|
||||
require.Contains(t, expectedAddrs, addr.String())
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,7 +242,7 @@ func TestFetchChannel(t *testing.T) {
|
||||
channelState := createTestChannel(t, cdb, openChannelOption())
|
||||
|
||||
// Next, attempt to fetch the channel by its chan point.
|
||||
dbChannel, err := cdb.FetchChannel(nil, channelState.FundingOutpoint)
|
||||
dbChannel, err := cdb.FetchChannel(channelState.FundingOutpoint)
|
||||
require.NoError(t, err, "unable to fetch channel")
|
||||
|
||||
// The decoded channel state should be identical to what we stored
|
||||
@ -257,7 +266,7 @@ func TestFetchChannel(t *testing.T) {
|
||||
uniqueOutputIndex.Add(1)
|
||||
channelState2.FundingOutpoint.Index = uniqueOutputIndex.Load()
|
||||
|
||||
_, err = cdb.FetchChannel(nil, channelState2.FundingOutpoint)
|
||||
_, err = cdb.FetchChannel(channelState2.FundingOutpoint)
|
||||
require.ErrorIs(t, err, ErrChannelNotFound)
|
||||
|
||||
chanID2 := lnwire.NewChanIDFromOutPoint(channelState2.FundingOutpoint)
|
||||
@ -397,7 +406,7 @@ func TestRestoreChannelShells(t *testing.T) {
|
||||
|
||||
// We should also be able to find the channel if we query for it
|
||||
// directly.
|
||||
_, err = cdb.FetchChannel(nil, channelShell.Chan.FundingOutpoint)
|
||||
_, err = cdb.FetchChannel(channelShell.Chan.FundingOutpoint)
|
||||
require.NoError(t, err, "unable to fetch channel")
|
||||
|
||||
// We should also be able to find the link node that was inserted by
|
||||
@ -446,7 +455,7 @@ func TestAbandonChannel(t *testing.T) {
|
||||
|
||||
// At this point, the channel should no longer be found in the set of
|
||||
// open channels.
|
||||
_, err = cdb.FetchChannel(nil, chanState.FundingOutpoint)
|
||||
_, err = cdb.FetchChannel(chanState.FundingOutpoint)
|
||||
if err != ErrChannelNotFound {
|
||||
t.Fatalf("channel should not have been found: %v", err)
|
||||
}
|
||||
@ -711,3 +720,28 @@ func TestFetchHistoricalChannel(t *testing.T) {
|
||||
t.Fatalf("expected chan not found, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func createLightningNode(priv *btcec.PrivateKey) *models.LightningNode {
|
||||
updateTime := rand.Int63()
|
||||
|
||||
pub := priv.PubKey().SerializeCompressed()
|
||||
n := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
AuthSigBytes: testSig.Serialize(),
|
||||
LastUpdate: time.Unix(updateTime, 0),
|
||||
Color: color.RGBA{1, 2, 3, 0},
|
||||
Alias: "kek" + string(pub),
|
||||
Features: testFeatures,
|
||||
Addresses: testAddrs,
|
||||
}
|
||||
copy(n.PubKeyBytes[:], priv.PubKey().SerializeCompressed())
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func createTestVertex(t *testing.T) *models.LightningNode {
|
||||
priv, err := btcec.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
return createLightningNode(priv)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package channeldb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
@ -43,57 +42,6 @@ var (
|
||||
// created.
|
||||
ErrMetaNotFound = fmt.Errorf("unable to locate meta information")
|
||||
|
||||
// ErrClosedScidsNotFound is returned when the closed scid bucket
|
||||
// hasn't been created.
|
||||
ErrClosedScidsNotFound = fmt.Errorf("closed scid bucket doesn't exist")
|
||||
|
||||
// ErrGraphNotFound is returned when at least one of the components of
|
||||
// graph doesn't exist.
|
||||
ErrGraphNotFound = fmt.Errorf("graph bucket not initialized")
|
||||
|
||||
// ErrGraphNeverPruned is returned when graph was never pruned.
|
||||
ErrGraphNeverPruned = fmt.Errorf("graph never pruned")
|
||||
|
||||
// ErrSourceNodeNotSet is returned if the source node of the graph
|
||||
// hasn't been added The source node is the center node within a
|
||||
// star-graph.
|
||||
ErrSourceNodeNotSet = fmt.Errorf("source node does not exist")
|
||||
|
||||
// ErrGraphNodesNotFound is returned in case none of the nodes has
|
||||
// been added in graph node bucket.
|
||||
ErrGraphNodesNotFound = fmt.Errorf("no graph nodes exist")
|
||||
|
||||
// ErrGraphNoEdgesFound is returned in case of none of the channel/edges
|
||||
// has been added in graph edge bucket.
|
||||
ErrGraphNoEdgesFound = fmt.Errorf("no graph edges exist")
|
||||
|
||||
// ErrGraphNodeNotFound is returned when we're unable to find the target
|
||||
// node.
|
||||
ErrGraphNodeNotFound = fmt.Errorf("unable to find node")
|
||||
|
||||
// ErrEdgeNotFound is returned when an edge for the target chanID
|
||||
// can't be found.
|
||||
ErrEdgeNotFound = fmt.Errorf("edge not found")
|
||||
|
||||
// ErrZombieEdge is an error returned when we attempt to look up an edge
|
||||
// but it is marked as a zombie within the zombie index.
|
||||
ErrZombieEdge = errors.New("edge marked as zombie")
|
||||
|
||||
// ErrZombieEdgeNotFound is an error returned when we attempt to find an
|
||||
// edge in the zombie index which is not there.
|
||||
ErrZombieEdgeNotFound = errors.New("edge not found in zombie index")
|
||||
|
||||
// ErrEdgeAlreadyExist is returned when edge with specific
|
||||
// channel id can't be added because it already exist.
|
||||
ErrEdgeAlreadyExist = fmt.Errorf("edge already exist")
|
||||
|
||||
// ErrNodeAliasNotFound is returned when alias for node can't be found.
|
||||
ErrNodeAliasNotFound = fmt.Errorf("alias for node not found")
|
||||
|
||||
// ErrUnknownAddressType is returned when a node's addressType is not
|
||||
// an expected value.
|
||||
ErrUnknownAddressType = fmt.Errorf("address type cannot be resolved")
|
||||
|
||||
// ErrNoClosedChannels is returned when a node is queries for all the
|
||||
// channels it has closed, but it hasn't yet closed any channels.
|
||||
ErrNoClosedChannels = fmt.Errorf("no channel have been closed yet")
|
||||
@ -102,24 +50,8 @@ var (
|
||||
// to the log not having any recorded events.
|
||||
ErrNoForwardingEvents = fmt.Errorf("no recorded forwarding events")
|
||||
|
||||
// ErrEdgePolicyOptionalFieldNotFound is an error returned if a channel
|
||||
// policy field is not found in the db even though its message flags
|
||||
// indicate it should be.
|
||||
ErrEdgePolicyOptionalFieldNotFound = fmt.Errorf("optional field not " +
|
||||
"present")
|
||||
|
||||
// ErrChanAlreadyExists is return when the caller attempts to create a
|
||||
// channel with a channel point that is already present in the
|
||||
// database.
|
||||
ErrChanAlreadyExists = fmt.Errorf("channel already exists")
|
||||
)
|
||||
|
||||
// ErrTooManyExtraOpaqueBytes creates an error which should be returned if the
|
||||
// caller attempts to write an announcement message which bares too many extra
|
||||
// opaque bytes. We limit this value in order to ensure that we don't waste
|
||||
// disk space due to nodes unnecessarily padding out their announcements with
|
||||
// garbage data.
|
||||
func ErrTooManyExtraOpaqueBytes(numBytes int) error {
|
||||
return fmt.Errorf("max allowed number of opaque bytes is %v, received "+
|
||||
"%v bytes", MaxAllowedExtraOpaqueBytes, numBytes)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package channeldb
|
||||
|
||||
import (
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
@ -23,15 +23,11 @@ func initHintCache(t *testing.T) *HeightHintCache {
|
||||
func initHintCacheWithConfig(t *testing.T, cfg CacheConfig) *HeightHintCache {
|
||||
t.Helper()
|
||||
|
||||
db, err := Open(t.TempDir())
|
||||
require.NoError(t, err, "unable to create db")
|
||||
db := OpenForTesting(t, t.TempDir())
|
||||
|
||||
hintCache, err := NewHeightHintCache(cfg, db.Backend)
|
||||
require.NoError(t, err, "unable to create hint cache")
|
||||
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, db.Close())
|
||||
})
|
||||
|
||||
return hintCache
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
invpkg "github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
invpkg "github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcwallet/walletdb"
|
||||
"github.com/go-errors/errors"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -22,14 +23,11 @@ func applyMigration(t *testing.T, beforeMigration, afterMigration func(d *DB),
|
||||
cdb.dryRun = dryRun
|
||||
|
||||
// Create a test node that will be our source node.
|
||||
testNode, err := createTestVertex(cdb)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
graph := cdb.ChannelGraph()
|
||||
if err := graph.SetSourceNode(testNode); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
testNode := createTestVertex(t)
|
||||
|
||||
graph, err := graphdb.MakeTestGraph(t)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, graph.SetSourceNode(testNode))
|
||||
|
||||
// beforeMigration usually used for populating the database
|
||||
// with test data.
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
)
|
||||
|
||||
@ -273,7 +274,7 @@ func serializeLinkNode(w io.Writer, l *LinkNode) error {
|
||||
}
|
||||
|
||||
for _, addr := range l.Addresses {
|
||||
if err := serializeAddr(w, addr); err != nil {
|
||||
if err := graphdb.SerializeAddr(w, addr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -315,7 +316,7 @@ func deserializeLinkNode(r io.Reader) (*LinkNode, error) {
|
||||
|
||||
node.Addresses = make([]net.Addr, numAddrs)
|
||||
for i := uint32(0); i < numAddrs; i++ {
|
||||
addr, err := deserializeAddr(r)
|
||||
addr, err := graphdb.DeserializeAddr(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package channeldb
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -35,30 +32,8 @@ type OptionalMiragtionConfig struct {
|
||||
|
||||
// Options holds parameters for tuning and customizing a channeldb.DB.
|
||||
type Options struct {
|
||||
kvdb.BoltBackendConfig
|
||||
OptionalMiragtionConfig
|
||||
|
||||
// RejectCacheSize is the maximum number of rejectCacheEntries to hold
|
||||
// in the rejection cache.
|
||||
RejectCacheSize int
|
||||
|
||||
// ChannelCacheSize is the maximum number of ChannelEdges to hold in the
|
||||
// channel cache.
|
||||
ChannelCacheSize int
|
||||
|
||||
// BatchCommitInterval is the maximum duration the batch schedulers will
|
||||
// wait before attempting to commit a pending set of updates.
|
||||
BatchCommitInterval time.Duration
|
||||
|
||||
// PreAllocCacheNumNodes is the number of nodes we expect to be in the
|
||||
// graph cache, so we can pre-allocate the map accordingly.
|
||||
PreAllocCacheNumNodes int
|
||||
|
||||
// UseGraphCache denotes whether the in-memory graph cache should be
|
||||
// used or a fallback version that uses the underlying database for
|
||||
// path finding.
|
||||
UseGraphCache bool
|
||||
|
||||
// NoMigration specifies that underlying backend was opened in read-only
|
||||
// mode and migrations shouldn't be performed. This can be useful for
|
||||
// applications that use the channeldb package as a library.
|
||||
@ -87,17 +62,7 @@ type Options struct {
|
||||
// DefaultOptions returns an Options populated with default values.
|
||||
func DefaultOptions() Options {
|
||||
return Options{
|
||||
BoltBackendConfig: kvdb.BoltBackendConfig{
|
||||
NoFreelistSync: true,
|
||||
AutoCompact: false,
|
||||
AutoCompactMinAge: kvdb.DefaultBoltAutoCompactMinAge,
|
||||
DBTimeout: kvdb.DefaultDBTimeout,
|
||||
},
|
||||
OptionalMiragtionConfig: OptionalMiragtionConfig{},
|
||||
RejectCacheSize: DefaultRejectCacheSize,
|
||||
ChannelCacheSize: DefaultChannelCacheSize,
|
||||
PreAllocCacheNumNodes: DefaultPreAllocCacheNumNodes,
|
||||
UseGraphCache: true,
|
||||
NoMigration: false,
|
||||
clock: clock.NewDefaultClock(),
|
||||
}
|
||||
@ -106,34 +71,6 @@ func DefaultOptions() Options {
|
||||
// OptionModifier is a function signature for modifying the default Options.
|
||||
type OptionModifier func(*Options)
|
||||
|
||||
// OptionSetRejectCacheSize sets the RejectCacheSize to n.
|
||||
func OptionSetRejectCacheSize(n int) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.RejectCacheSize = n
|
||||
}
|
||||
}
|
||||
|
||||
// OptionSetChannelCacheSize sets the ChannelCacheSize to n.
|
||||
func OptionSetChannelCacheSize(n int) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.ChannelCacheSize = n
|
||||
}
|
||||
}
|
||||
|
||||
// OptionSetPreAllocCacheNumNodes sets the PreAllocCacheNumNodes to n.
|
||||
func OptionSetPreAllocCacheNumNodes(n int) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.PreAllocCacheNumNodes = n
|
||||
}
|
||||
}
|
||||
|
||||
// OptionSetUseGraphCache sets the UseGraphCache option to the given value.
|
||||
func OptionSetUseGraphCache(use bool) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.UseGraphCache = use
|
||||
}
|
||||
}
|
||||
|
||||
// OptionNoRevLogAmtData sets the NoRevLogAmtData option to the given value. If
|
||||
// it is set to true then amount data will not be stored in the revocation log.
|
||||
func OptionNoRevLogAmtData(noAmtData bool) OptionModifier {
|
||||
@ -142,36 +79,6 @@ func OptionNoRevLogAmtData(noAmtData bool) OptionModifier {
|
||||
}
|
||||
}
|
||||
|
||||
// OptionSetSyncFreelist allows the database to sync its freelist.
|
||||
func OptionSetSyncFreelist(b bool) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.NoFreelistSync = !b
|
||||
}
|
||||
}
|
||||
|
||||
// OptionAutoCompact turns on automatic database compaction on startup.
|
||||
func OptionAutoCompact() OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.AutoCompact = true
|
||||
}
|
||||
}
|
||||
|
||||
// OptionAutoCompactMinAge sets the minimum age for automatic database
|
||||
// compaction.
|
||||
func OptionAutoCompactMinAge(minAge time.Duration) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.AutoCompactMinAge = minAge
|
||||
}
|
||||
}
|
||||
|
||||
// OptionSetBatchCommitInterval sets the batch commit interval for the internval
|
||||
// batch schedulers.
|
||||
func OptionSetBatchCommitInterval(interval time.Duration) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.BatchCommitInterval = interval
|
||||
}
|
||||
}
|
||||
|
||||
// OptionNoMigration allows the database to be opened in read only mode by
|
||||
// disabling migrations.
|
||||
func OptionNoMigration(b bool) OptionModifier {
|
||||
|
@ -1,27 +0,0 @@
|
||||
package channeldb_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestDefaultOptions tests the default options are created as intended.
|
||||
func TestDefaultOptions(t *testing.T) {
|
||||
opts := channeldb.DefaultOptions()
|
||||
|
||||
require.True(t, opts.NoFreelistSync)
|
||||
require.False(t, opts.AutoCompact)
|
||||
require.Equal(
|
||||
t, kvdb.DefaultBoltAutoCompactMinAge, opts.AutoCompactMinAge,
|
||||
)
|
||||
require.Equal(t, kvdb.DefaultDBTimeout, opts.DBTimeout)
|
||||
require.Equal(
|
||||
t, channeldb.DefaultRejectCacheSize, opts.RejectCacheSize,
|
||||
)
|
||||
require.Equal(
|
||||
t, channeldb.DefaultChannelCacheSize, opts.ChannelCacheSize,
|
||||
)
|
||||
}
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
)
|
||||
@ -164,7 +165,7 @@ func putReport(tx kvdb.RwTx, chainHash chainhash.Hash,
|
||||
|
||||
// Finally write our outpoint to be used as the key for this record.
|
||||
var keyBuf bytes.Buffer
|
||||
if err := writeOutpoint(&keyBuf, &report.OutPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&keyBuf, &report.OutPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -317,7 +318,7 @@ func fetchReportWriteBucket(tx kvdb.RwTx, chainHash chainhash.Hash,
|
||||
}
|
||||
|
||||
var chanPointBuf bytes.Buffer
|
||||
if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -341,7 +342,7 @@ func fetchReportReadBucket(tx kvdb.RTx, chainHash chainhash.Hash,
|
||||
// With the bucket for the node and chain fetched, we can now go down
|
||||
// another level, for the channel itself.
|
||||
var chanPointBuf bytes.Buffer
|
||||
if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -137,7 +138,7 @@ func TestFetchChannelWriteBucket(t *testing.T) {
|
||||
error) {
|
||||
|
||||
var chanPointBuf bytes.Buffer
|
||||
err := writeOutpoint(&chanPointBuf, &testChanPoint1)
|
||||
err := graphdb.WriteOutpoint(&chanPointBuf, &testChanPoint1)
|
||||
require.NoError(t, err)
|
||||
|
||||
return chainHash.CreateBucketIfNotExists(chanPointBuf.Bytes())
|
||||
|
@ -144,7 +144,7 @@ func (c *ChannelNotifier) NotifyPendingOpenChannelEvent(chanPoint wire.OutPoint,
|
||||
// channel has gone from pending open to open.
|
||||
func (c *ChannelNotifier) NotifyOpenChannelEvent(chanPoint wire.OutPoint) {
|
||||
// Fetch the relevant channel from the database.
|
||||
channel, err := c.chanDB.FetchChannel(nil, chanPoint)
|
||||
channel, err := c.chanDB.FetchChannel(chanPoint)
|
||||
if err != nil {
|
||||
log.Warnf("Unable to fetch open channel from the db: %v", err)
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/funding"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
@ -900,18 +901,10 @@ func (d *RPCSignerWalletImpl) BuildChainControl(
|
||||
type DatabaseInstances struct {
|
||||
// GraphDB is the database that stores the channel graph used for path
|
||||
// finding.
|
||||
//
|
||||
// NOTE/TODO: This currently _needs_ to be the same instance as the
|
||||
// ChanStateDB below until the separation of the two databases is fully
|
||||
// complete!
|
||||
GraphDB *channeldb.DB
|
||||
GraphDB *graphdb.ChannelGraph
|
||||
|
||||
// ChanStateDB is the database that stores all of our node's channel
|
||||
// state.
|
||||
//
|
||||
// NOTE/TODO: This currently _needs_ to be the same instance as the
|
||||
// GraphDB above until the separation of the two databases is fully
|
||||
// complete!
|
||||
ChanStateDB *channeldb.DB
|
||||
|
||||
// HeightHintDB is the database that stores height hints for spends.
|
||||
@ -1022,16 +1015,37 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
"instances")
|
||||
}
|
||||
|
||||
graphDBOptions := []graphdb.OptionModifier{
|
||||
graphdb.WithRejectCacheSize(cfg.Caches.RejectCacheSize),
|
||||
graphdb.WithChannelCacheSize(cfg.Caches.ChannelCacheSize),
|
||||
graphdb.WithBatchCommitInterval(cfg.DB.BatchCommitInterval),
|
||||
graphdb.WithUseGraphCache(!cfg.DB.NoGraphCache),
|
||||
}
|
||||
|
||||
// We want to pre-allocate the channel graph cache according to what we
|
||||
// expect for mainnet to speed up memory allocation.
|
||||
if cfg.ActiveNetParams.Name == chaincfg.MainNetParams.Name {
|
||||
graphDBOptions = append(
|
||||
graphDBOptions, graphdb.WithPreAllocCacheNumNodes(
|
||||
graphdb.DefaultPreAllocCacheNumNodes,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
dbs.GraphDB, err = graphdb.NewChannelGraph(
|
||||
databaseBackends.GraphDB, graphDBOptions...,
|
||||
)
|
||||
if err != nil {
|
||||
cleanUp()
|
||||
|
||||
err := fmt.Errorf("unable to open graph DB: %w", err)
|
||||
d.logger.Error(err)
|
||||
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
dbOptions := []channeldb.OptionModifier{
|
||||
channeldb.OptionSetRejectCacheSize(cfg.Caches.RejectCacheSize),
|
||||
channeldb.OptionSetChannelCacheSize(
|
||||
cfg.Caches.ChannelCacheSize,
|
||||
),
|
||||
channeldb.OptionSetBatchCommitInterval(
|
||||
cfg.DB.BatchCommitInterval,
|
||||
),
|
||||
channeldb.OptionDryRunMigration(cfg.DryRunMigration),
|
||||
channeldb.OptionSetUseGraphCache(!cfg.DB.NoGraphCache),
|
||||
channeldb.OptionKeepFailedPaymentAttempts(
|
||||
cfg.KeepFailedPaymentAttempts,
|
||||
),
|
||||
@ -1042,27 +1056,17 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
channeldb.OptionNoRevLogAmtData(cfg.DB.NoRevLogAmtData),
|
||||
}
|
||||
|
||||
// We want to pre-allocate the channel graph cache according to what we
|
||||
// expect for mainnet to speed up memory allocation.
|
||||
if cfg.ActiveNetParams.Name == chaincfg.MainNetParams.Name {
|
||||
dbOptions = append(
|
||||
dbOptions, channeldb.OptionSetPreAllocCacheNumNodes(
|
||||
channeldb.DefaultPreAllocCacheNumNodes,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// Otherwise, we'll open two instances, one for the state we only need
|
||||
// locally, and the other for things we want to ensure are replicated.
|
||||
dbs.GraphDB, err = channeldb.CreateWithBackend(
|
||||
databaseBackends.GraphDB, dbOptions...,
|
||||
dbs.ChanStateDB, err = channeldb.CreateWithBackend(
|
||||
databaseBackends.ChanStateDB, dbOptions...,
|
||||
)
|
||||
switch {
|
||||
// Give the DB a chance to dry run the migration. Since we know that
|
||||
// both the channel state and graph DBs are still always behind the same
|
||||
// backend, we know this would be applied to both of those DBs.
|
||||
case err == channeldb.ErrDryRunMigrationOK:
|
||||
d.logger.Infof("Graph DB dry run migration successful")
|
||||
d.logger.Infof("Channel DB dry run migration successful")
|
||||
return nil, nil, err
|
||||
|
||||
case err != nil:
|
||||
@ -1073,27 +1077,14 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// For now, we don't _actually_ split the graph and channel state DBs on
|
||||
// the code level. Since they both are based upon the *channeldb.DB
|
||||
// struct it will require more refactoring to fully separate them. With
|
||||
// the full remote mode we at least know for now that they both point to
|
||||
// the same DB backend (and also namespace within that) so we only need
|
||||
// to apply any migration once.
|
||||
//
|
||||
// TODO(guggero): Once the full separation of anything graph related
|
||||
// from the channeldb.DB is complete, the decorated instance of the
|
||||
// channel state DB should be created here individually instead of just
|
||||
// using the same struct (and DB backend) instance.
|
||||
dbs.ChanStateDB = dbs.GraphDB
|
||||
|
||||
// Instantiate a native SQL invoice store if the flag is set.
|
||||
if d.cfg.DB.UseNativeSQL {
|
||||
// KV invoice db resides in the same database as the graph and
|
||||
// channel state DB. Let's query the database to see if we have
|
||||
// any invoices there. If we do, we won't allow the user to
|
||||
// start lnd with native SQL enabled, as we don't currently
|
||||
// migrate the invoices to the new database schema.
|
||||
invoiceSlice, err := dbs.GraphDB.QueryInvoices(
|
||||
// KV invoice db resides in the same database as the channel
|
||||
// state DB. Let's query the database to see if we have any
|
||||
// invoices there. If we do, we won't allow the user to start
|
||||
// lnd with native SQL enabled, as we don't currently migrate
|
||||
// the invoices to the new database schema.
|
||||
invoiceSlice, err := dbs.ChanStateDB.QueryInvoices(
|
||||
ctx, invoices.InvoiceQuery{
|
||||
NumMaxInvoices: 1,
|
||||
},
|
||||
@ -1127,7 +1118,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
executor, clock.NewDefaultClock(),
|
||||
)
|
||||
} else {
|
||||
dbs.InvoiceDB = dbs.GraphDB
|
||||
dbs.InvoiceDB = dbs.ChanStateDB
|
||||
}
|
||||
|
||||
// Wrap the watchtower client DB and make sure we clean up.
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/labels"
|
||||
@ -1856,7 +1857,8 @@ func (rs *RetributionStore) Add(ret *retributionInfo) error {
|
||||
}
|
||||
|
||||
var outBuf bytes.Buffer
|
||||
if err := writeOutpoint(&outBuf, &ret.chanPoint); err != nil {
|
||||
err = graphdb.WriteOutpoint(&outBuf, &ret.chanPoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1907,7 +1909,8 @@ func (rs *RetributionStore) IsBreached(chanPoint *wire.OutPoint) (bool, error) {
|
||||
}
|
||||
|
||||
var chanBuf bytes.Buffer
|
||||
if err := writeOutpoint(&chanBuf, chanPoint); err != nil {
|
||||
err := graphdb.WriteOutpoint(&chanBuf, chanPoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1947,7 +1950,8 @@ func (rs *RetributionStore) Remove(chanPoint *wire.OutPoint) error {
|
||||
|
||||
// Serialize the channel point we are intending to remove.
|
||||
var chanBuf bytes.Buffer
|
||||
if err := writeOutpoint(&chanBuf, chanPoint); err != nil {
|
||||
err = graphdb.WriteOutpoint(&chanBuf, chanPoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chanBytes := chanBuf.Bytes()
|
||||
@ -2017,7 +2021,7 @@ func (ret *retributionInfo) Encode(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := writeOutpoint(w, &ret.chanPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(w, &ret.chanPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -2057,7 +2061,7 @@ func (ret *retributionInfo) Decode(r io.Reader) error {
|
||||
}
|
||||
ret.commitHash = *hash
|
||||
|
||||
if err := readOutpoint(r, &ret.chanPoint); err != nil {
|
||||
if err := graphdb.ReadOutpoint(r, &ret.chanPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -2100,7 +2104,7 @@ func (bo *breachedOutput) Encode(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := writeOutpoint(w, &bo.outpoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(w, &bo.outpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -2131,7 +2135,7 @@ func (bo *breachedOutput) Decode(r io.Reader) error {
|
||||
}
|
||||
bo.amt = btcutil.Amount(binary.BigEndian.Uint64(scratch[:8]))
|
||||
|
||||
if err := readOutpoint(r, &bo.outpoint); err != nil {
|
||||
if err := graphdb.ReadOutpoint(r, &bo.outpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -635,15 +635,6 @@ func TestMockRetributionStore(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func makeTestChannelDB(t *testing.T) (*channeldb.DB, error) {
|
||||
db, err := channeldb.Open(t.TempDir())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// TestChannelDBRetributionStore instantiates a retributionStore backed by a
|
||||
// channeldb.DB, and tests its behavior using the general RetributionStore test
|
||||
// suite.
|
||||
@ -654,25 +645,19 @@ func TestChannelDBRetributionStore(t *testing.T) {
|
||||
t.Run(
|
||||
"channeldbDBRetributionStore."+test.name,
|
||||
func(tt *testing.T) {
|
||||
db, err := makeTestChannelDB(t)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open channeldb: %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
db := channeldb.OpenForTesting(t, t.TempDir())
|
||||
|
||||
restartDb := func() RetributionStorer {
|
||||
// Close and reopen channeldb
|
||||
if err = db.Close(); err != nil {
|
||||
if err := db.Close(); err != nil {
|
||||
t.Fatalf("unable to close "+
|
||||
"channeldb during "+
|
||||
"restart: %v",
|
||||
err)
|
||||
}
|
||||
db, err = channeldb.Open(db.Path())
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open "+
|
||||
"channeldb: %v", err)
|
||||
}
|
||||
db = channeldb.OpenForTesting(
|
||||
t, db.Path(),
|
||||
)
|
||||
|
||||
return NewRetributionStore(db)
|
||||
}
|
||||
@ -2279,21 +2264,8 @@ func createInitChannels(t *testing.T) (
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
dbAlice, err := channeldb.Open(t.TempDir())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, dbAlice.Close())
|
||||
})
|
||||
|
||||
dbBob, err := channeldb.Open(t.TempDir())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, dbBob.Close())
|
||||
})
|
||||
dbAlice := channeldb.OpenForTesting(t, t.TempDir())
|
||||
dbBob := channeldb.OpenForTesting(t, t.TempDir())
|
||||
|
||||
estimator := chainfee.NewStaticEstimator(12500, 0)
|
||||
feePerKw, err := estimator.EstimateFeePerKW(1)
|
||||
|
@ -13,9 +13,9 @@ import (
|
||||
"github.com/btcsuite/btcwallet/walletdb"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/labels"
|
||||
@ -304,9 +304,7 @@ func (a *arbChannel) NewAnchorResolutions() (*lnwallet.AnchorResolutions,
|
||||
// same instance that is used by the link.
|
||||
chanPoint := a.channel.FundingOutpoint
|
||||
|
||||
channel, err := a.c.chanSource.ChannelStateDB().FetchChannel(
|
||||
nil, chanPoint,
|
||||
)
|
||||
channel, err := a.c.chanSource.ChannelStateDB().FetchChannel(chanPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -359,9 +357,7 @@ func (a *arbChannel) ForceCloseChan() (*wire.MsgTx, error) {
|
||||
// Now that we know the link can't mutate the channel
|
||||
// state, we'll read the channel from disk the target
|
||||
// channel according to its channel point.
|
||||
channel, err := a.c.chanSource.ChannelStateDB().FetchChannel(
|
||||
nil, chanPoint,
|
||||
)
|
||||
channel, err := a.c.chanSource.ChannelStateDB().FetchChannel(chanPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/lntest/mock"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
@ -22,13 +22,7 @@ import (
|
||||
func TestChainArbitratorRepublishCloses(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, err := channeldb.Open(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, db.Close())
|
||||
})
|
||||
db := channeldb.OpenForTesting(t, t.TempDir())
|
||||
|
||||
// Create 10 test channels and sync them to the database.
|
||||
const numChans = 10
|
||||
@ -139,11 +133,7 @@ func TestChainArbitratorRepublishCloses(t *testing.T) {
|
||||
func TestResolveContract(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, err := channeldb.Open(t.TempDir())
|
||||
require.NoError(t, err, "unable to open db")
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, db.Close())
|
||||
})
|
||||
db := channeldb.OpenForTesting(t, t.TempDir())
|
||||
|
||||
// With the DB created, we'll make a new channel, and mark it as
|
||||
// pending open within the database.
|
||||
|
@ -15,8 +15,8 @@ import (
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
|
@ -15,9 +15,9 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lntest/mock"
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lntest/mock"
|
||||
|
@ -10,8 +10,8 @@ import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
sphinx "github.com/lightningnetwork/lightning-onion"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnmock"
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/labels"
|
||||
"github.com/lightningnetwork/lnd/lnutils"
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnmock"
|
||||
|
@ -14,8 +14,8 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
|
@ -2,7 +2,7 @@ package contractcourt
|
||||
|
||||
import (
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
)
|
||||
|
||||
type mockHTLCNotifier struct {
|
||||
|
@ -3,7 +3,7 @@ package contractcourt
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
)
|
||||
|
||||
@ -221,7 +222,7 @@ func prefixOutputKey(statePrefix []byte,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := writeOutpoint(&pfxOutputBuffer, &outpoint)
|
||||
err := graphdb.WriteOutpoint(&pfxOutputBuffer, &outpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -738,7 +739,9 @@ func (ns *NurseryStore) ListChannels() ([]wire.OutPoint, error) {
|
||||
|
||||
return chanIndex.ForEach(func(chanBytes, _ []byte) error {
|
||||
var chanPoint wire.OutPoint
|
||||
err := readOutpoint(bytes.NewReader(chanBytes), &chanPoint)
|
||||
err := graphdb.ReadOutpoint(
|
||||
bytes.NewReader(chanBytes), &chanPoint,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -804,12 +807,13 @@ func (ns *NurseryStore) RemoveChannel(chanPoint *wire.OutPoint) error {
|
||||
// Serialize the provided channel point, such that we can delete
|
||||
// the mature channel bucket.
|
||||
var chanBuffer bytes.Buffer
|
||||
if err := writeOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
err := graphdb.WriteOutpoint(&chanBuffer, chanPoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chanBytes := chanBuffer.Bytes()
|
||||
|
||||
err := ns.forChanOutputs(tx, chanPoint, func(k, v []byte) error {
|
||||
err = ns.forChanOutputs(tx, chanPoint, func(k, v []byte) error {
|
||||
if !bytes.HasPrefix(k, gradPrefix) {
|
||||
return ErrImmatureChannel
|
||||
}
|
||||
@ -959,7 +963,7 @@ func (ns *NurseryStore) createChannelBucket(tx kvdb.RwTx,
|
||||
// Serialize the provided channel point, as this provides the name of
|
||||
// the channel bucket of interest.
|
||||
var chanBuffer bytes.Buffer
|
||||
if err := writeOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -989,7 +993,7 @@ func (ns *NurseryStore) getChannelBucket(tx kvdb.RTx,
|
||||
// Serialize the provided channel point and return the bucket matching
|
||||
// the serialized key.
|
||||
var chanBuffer bytes.Buffer
|
||||
if err := writeOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1017,7 +1021,7 @@ func (ns *NurseryStore) getChannelBucketWrite(tx kvdb.RwTx,
|
||||
// Serialize the provided channel point and return the bucket matching
|
||||
// the serialized key.
|
||||
var chanBuffer bytes.Buffer
|
||||
if err := writeOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1142,7 +1146,7 @@ func (ns *NurseryStore) createHeightChanBucket(tx kvdb.RwTx,
|
||||
// Serialize the provided channel point, as this generates the name of
|
||||
// the subdirectory corresponding to the channel of interest.
|
||||
var chanBuffer bytes.Buffer
|
||||
if err := writeOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chanBytes := chanBuffer.Bytes()
|
||||
@ -1168,7 +1172,7 @@ func (ns *NurseryStore) getHeightChanBucketWrite(tx kvdb.RwTx,
|
||||
// Serialize the provided channel point, which generates the key for
|
||||
// looking up the proper height-channel bucket inside the height bucket.
|
||||
var chanBuffer bytes.Buffer
|
||||
if err := writeOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
return nil
|
||||
}
|
||||
chanBytes := chanBuffer.Bytes()
|
||||
@ -1312,7 +1316,7 @@ func (ns *NurseryStore) removeOutputFromHeight(tx kvdb.RwTx, height uint32,
|
||||
}
|
||||
|
||||
var chanBuffer bytes.Buffer
|
||||
if err := writeOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
if err := graphdb.WriteOutpoint(&chanBuffer, chanPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -65,12 +65,9 @@ func copyChannelState(t *testing.T, state *channeldb.OpenChannel) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newDb, err := channeldb.Open(tempDbPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newDB := channeldb.OpenForTesting(t, tempDbPath)
|
||||
|
||||
chans, err := newDb.ChannelStateDB().FetchAllChannels()
|
||||
chans, err := newDB.ChannelStateDB().FetchAllChannels()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/labels"
|
||||
"github.com/lightningnetwork/lnd/lnutils"
|
||||
@ -1466,10 +1467,10 @@ func (k *kidOutput) Encode(w io.Writer) error {
|
||||
}
|
||||
|
||||
op := k.OutPoint()
|
||||
if err := writeOutpoint(w, &op); err != nil {
|
||||
if err := graphdb.WriteOutpoint(w, &op); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeOutpoint(w, k.OriginChanPoint()); err != nil {
|
||||
if err := graphdb.WriteOutpoint(w, k.OriginChanPoint()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1521,11 +1522,12 @@ func (k *kidOutput) Decode(r io.Reader) error {
|
||||
}
|
||||
k.amt = btcutil.Amount(byteOrder.Uint64(scratch[:]))
|
||||
|
||||
if err := readOutpoint(io.LimitReader(r, 40), &k.outpoint); err != nil {
|
||||
err := graphdb.ReadOutpoint(io.LimitReader(r, 40), &k.outpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := readOutpoint(io.LimitReader(r, 40), &k.originChanPoint)
|
||||
err = graphdb.ReadOutpoint(io.LimitReader(r, 40), &k.originChanPoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1577,40 +1579,6 @@ func (k *kidOutput) Decode(r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(bvu): copied from channeldb, remove repetition
|
||||
func writeOutpoint(w io.Writer, o *wire.OutPoint) error {
|
||||
// TODO(roasbeef): make all scratch buffers on the stack
|
||||
scratch := make([]byte, 4)
|
||||
|
||||
// TODO(roasbeef): write raw 32 bytes instead of wasting the extra
|
||||
// byte.
|
||||
if err := wire.WriteVarBytes(w, 0, o.Hash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
byteOrder.PutUint32(scratch, o.Index)
|
||||
_, err := w.Write(scratch)
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(bvu): copied from channeldb, remove repetition
|
||||
func readOutpoint(r io.Reader, o *wire.OutPoint) error {
|
||||
scratch := make([]byte, 4)
|
||||
|
||||
txid, err := wire.ReadVarBytes(r, 0, 32, "prevout")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copy(o.Hash[:], txid)
|
||||
|
||||
if _, err := r.Read(scratch); err != nil {
|
||||
return err
|
||||
}
|
||||
o.Index = byteOrder.Uint32(scratch)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Compile-time constraint to ensure kidOutput implements the
|
||||
// Input interface.
|
||||
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/netann"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
@ -36,7 +36,7 @@ type ChannelGraphTimeSeries interface {
|
||||
// ID's represents the ID's that we don't know of which were in the
|
||||
// passed superSet.
|
||||
FilterKnownChanIDs(chain chainhash.Hash,
|
||||
superSet []channeldb.ChannelUpdateInfo,
|
||||
superSet []graphdb.ChannelUpdateInfo,
|
||||
isZombieChan func(time.Time, time.Time) bool) (
|
||||
[]lnwire.ShortChannelID, error)
|
||||
|
||||
@ -45,7 +45,7 @@ type ChannelGraphTimeSeries interface {
|
||||
// grouped by their common block height. We'll use this to to a remote
|
||||
// peer's QueryChannelRange message.
|
||||
FilterChannelRange(chain chainhash.Hash, startHeight, endHeight uint32,
|
||||
withTimestamps bool) ([]channeldb.BlockChannelRange, error)
|
||||
withTimestamps bool) ([]graphdb.BlockChannelRange, error)
|
||||
|
||||
// FetchChanAnns returns a full set of channel announcements as well as
|
||||
// their updates that match the set of specified short channel ID's.
|
||||
@ -70,12 +70,12 @@ type ChannelGraphTimeSeries interface {
|
||||
// in-protocol channel range queries to quickly and efficiently synchronize our
|
||||
// channel state with all peers.
|
||||
type ChanSeries struct {
|
||||
graph *channeldb.ChannelGraph
|
||||
graph *graphdb.ChannelGraph
|
||||
}
|
||||
|
||||
// NewChanSeries constructs a new ChanSeries backed by a channeldb.ChannelGraph.
|
||||
// The returned ChanSeries implements the ChannelGraphTimeSeries interface.
|
||||
func NewChanSeries(graph *channeldb.ChannelGraph) *ChanSeries {
|
||||
func NewChanSeries(graph *graphdb.ChannelGraph) *ChanSeries {
|
||||
return &ChanSeries{
|
||||
graph: graph,
|
||||
}
|
||||
@ -200,7 +200,7 @@ func (c *ChanSeries) UpdatesInHorizon(chain chainhash.Hash,
|
||||
//
|
||||
// NOTE: This is part of the ChannelGraphTimeSeries interface.
|
||||
func (c *ChanSeries) FilterKnownChanIDs(_ chainhash.Hash,
|
||||
superSet []channeldb.ChannelUpdateInfo,
|
||||
superSet []graphdb.ChannelUpdateInfo,
|
||||
isZombieChan func(time.Time, time.Time) bool) (
|
||||
[]lnwire.ShortChannelID, error) {
|
||||
|
||||
@ -226,7 +226,7 @@ func (c *ChanSeries) FilterKnownChanIDs(_ chainhash.Hash,
|
||||
//
|
||||
// NOTE: This is part of the ChannelGraphTimeSeries interface.
|
||||
func (c *ChanSeries) FilterChannelRange(_ chainhash.Hash, startHeight,
|
||||
endHeight uint32, withTimestamps bool) ([]channeldb.BlockChannelRange,
|
||||
endHeight uint32, withTimestamps bool) ([]graphdb.BlockChannelRange,
|
||||
error) {
|
||||
|
||||
return c.graph.FilterChannelRange(
|
||||
|
@ -19,11 +19,11 @@ import (
|
||||
"github.com/lightningnetwork/lnd/batch"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnpeer"
|
||||
"github.com/lightningnetwork/lnd/lnutils"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
@ -1636,7 +1636,6 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error {
|
||||
edgesToUpdate []updateTuple
|
||||
)
|
||||
err := d.cfg.Graph.ForAllOutgoingChannels(func(
|
||||
_ kvdb.RTx,
|
||||
info *models.ChannelEdgeInfo,
|
||||
edge *models.ChannelEdgePolicy) error {
|
||||
|
||||
@ -1686,7 +1685,7 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error {
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil && err != channeldb.ErrGraphNoEdgesFound {
|
||||
if err != nil && !errors.Is(err, graphdb.ErrGraphNoEdgesFound) {
|
||||
return fmt.Errorf("unable to retrieve outgoing channels: %w",
|
||||
err)
|
||||
}
|
||||
@ -1963,7 +1962,7 @@ func (d *AuthenticatedGossiper) addNode(msg *lnwire.NodeAnnouncement,
|
||||
|
||||
timestamp := time.Unix(int64(msg.Timestamp), 0)
|
||||
features := lnwire.NewFeatureVector(msg.Features, lnwire.Features)
|
||||
node := &channeldb.LightningNode{
|
||||
node := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
LastUpdate: timestamp,
|
||||
Addresses: msg.Addresses,
|
||||
@ -2121,7 +2120,7 @@ func (d *AuthenticatedGossiper) processZombieUpdate(
|
||||
// come through again.
|
||||
err = d.cfg.Graph.MarkEdgeLive(scid)
|
||||
switch {
|
||||
case errors.Is(err, channeldb.ErrZombieEdgeNotFound):
|
||||
case errors.Is(err, graphdb.ErrZombieEdgeNotFound):
|
||||
log.Errorf("edge with chan_id=%v was not found in the "+
|
||||
"zombie index: %v", err)
|
||||
|
||||
@ -2166,7 +2165,7 @@ func (d *AuthenticatedGossiper) isMsgStale(msg lnwire.Message) bool {
|
||||
// If the channel cannot be found, it is most likely a leftover
|
||||
// message for a channel that was closed, so we can consider it
|
||||
// stale.
|
||||
if errors.Is(err, channeldb.ErrEdgeNotFound) {
|
||||
if errors.Is(err, graphdb.ErrEdgeNotFound) {
|
||||
return true
|
||||
}
|
||||
if err != nil {
|
||||
@ -2186,7 +2185,7 @@ func (d *AuthenticatedGossiper) isMsgStale(msg lnwire.Message) bool {
|
||||
// If the channel cannot be found, it is most likely a leftover
|
||||
// message for a channel that was closed, so we can consider it
|
||||
// stale.
|
||||
if errors.Is(err, channeldb.ErrEdgeNotFound) {
|
||||
if errors.Is(err, graphdb.ErrEdgeNotFound) {
|
||||
return true
|
||||
}
|
||||
if err != nil {
|
||||
@ -2936,7 +2935,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
|
||||
case err == nil:
|
||||
break
|
||||
|
||||
case errors.Is(err, channeldb.ErrZombieEdge):
|
||||
case errors.Is(err, graphdb.ErrZombieEdge):
|
||||
err = d.processZombieUpdate(chanInfo, graphScid, upd)
|
||||
if err != nil {
|
||||
log.Debug(err)
|
||||
@ -2949,11 +2948,11 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
|
||||
// needed to ensure the edge exists in the graph before
|
||||
// applying the update.
|
||||
fallthrough
|
||||
case errors.Is(err, channeldb.ErrGraphNotFound):
|
||||
case errors.Is(err, graphdb.ErrGraphNotFound):
|
||||
fallthrough
|
||||
case errors.Is(err, channeldb.ErrGraphNoEdgesFound):
|
||||
case errors.Is(err, graphdb.ErrGraphNoEdgesFound):
|
||||
fallthrough
|
||||
case errors.Is(err, channeldb.ErrEdgeNotFound):
|
||||
case errors.Is(err, graphdb.ErrEdgeNotFound):
|
||||
// If the edge corresponding to this ChannelUpdate was not
|
||||
// found in the graph, this might be a channel in the process
|
||||
// of being opened, and we haven't processed our own
|
||||
|
@ -24,11 +24,11 @@ import (
|
||||
"github.com/lightningnetwork/lnd/batch"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnpeer"
|
||||
"github.com/lightningnetwork/lnd/lntest/mock"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
@ -73,26 +73,11 @@ var (
|
||||
rebroadcastInterval = time.Hour * 1000000
|
||||
)
|
||||
|
||||
// makeTestDB creates a new instance of the ChannelDB for testing purposes.
|
||||
func makeTestDB(t *testing.T) (*channeldb.DB, error) {
|
||||
// Create channeldb for the first time.
|
||||
cdb, err := channeldb.Open(t.TempDir())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
cdb.Close()
|
||||
})
|
||||
|
||||
return cdb, nil
|
||||
}
|
||||
|
||||
type mockGraphSource struct {
|
||||
bestHeight uint32
|
||||
|
||||
mu sync.Mutex
|
||||
nodes []channeldb.LightningNode
|
||||
nodes []models.LightningNode
|
||||
infos map[uint64]models.ChannelEdgeInfo
|
||||
edges map[uint64][]models.ChannelEdgePolicy
|
||||
zombies map[uint64][][33]byte
|
||||
@ -112,7 +97,7 @@ func newMockRouter(height uint32) *mockGraphSource {
|
||||
|
||||
var _ graph.ChannelGraphSource = (*mockGraphSource)(nil)
|
||||
|
||||
func (r *mockGraphSource) AddNode(node *channeldb.LightningNode,
|
||||
func (r *mockGraphSource) AddNode(node *models.LightningNode,
|
||||
_ ...batch.SchedulerOption) error {
|
||||
|
||||
r.mu.Lock()
|
||||
@ -202,18 +187,19 @@ func (r *mockGraphSource) AddProof(chanID lnwire.ShortChannelID,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *mockGraphSource) ForEachNode(func(node *channeldb.LightningNode) error) error {
|
||||
func (r *mockGraphSource) ForEachNode(
|
||||
func(node *models.LightningNode) error) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *mockGraphSource) ForAllOutgoingChannels(cb func(tx kvdb.RTx,
|
||||
i *models.ChannelEdgeInfo,
|
||||
c *models.ChannelEdgePolicy) error) error {
|
||||
func (r *mockGraphSource) ForAllOutgoingChannels(cb func(
|
||||
i *models.ChannelEdgeInfo, c *models.ChannelEdgePolicy) error) error {
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
chans := make(map[uint64]channeldb.ChannelEdge)
|
||||
chans := make(map[uint64]graphdb.ChannelEdge)
|
||||
for _, info := range r.infos {
|
||||
info := info
|
||||
|
||||
@ -230,7 +216,7 @@ func (r *mockGraphSource) ForAllOutgoingChannels(cb func(tx kvdb.RTx,
|
||||
}
|
||||
|
||||
for _, channel := range chans {
|
||||
if err := cb(nil, channel.Info, channel.Policy1); err != nil {
|
||||
if err := cb(channel.Info, channel.Policy1); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -251,13 +237,13 @@ func (r *mockGraphSource) GetChannelByID(chanID lnwire.ShortChannelID) (
|
||||
if !ok {
|
||||
pubKeys, isZombie := r.zombies[chanIDInt]
|
||||
if !isZombie {
|
||||
return nil, nil, nil, channeldb.ErrEdgeNotFound
|
||||
return nil, nil, nil, graphdb.ErrEdgeNotFound
|
||||
}
|
||||
|
||||
return &models.ChannelEdgeInfo{
|
||||
NodeKey1Bytes: pubKeys[0],
|
||||
NodeKey2Bytes: pubKeys[1],
|
||||
}, nil, nil, channeldb.ErrZombieEdge
|
||||
}, nil, nil, graphdb.ErrZombieEdge
|
||||
}
|
||||
|
||||
edges := r.edges[chanID.ToUint64()]
|
||||
@ -279,7 +265,7 @@ func (r *mockGraphSource) GetChannelByID(chanID lnwire.ShortChannelID) (
|
||||
}
|
||||
|
||||
func (r *mockGraphSource) FetchLightningNode(
|
||||
nodePub route.Vertex) (*channeldb.LightningNode, error) {
|
||||
nodePub route.Vertex) (*models.LightningNode, error) {
|
||||
|
||||
for _, node := range r.nodes {
|
||||
if bytes.Equal(nodePub[:], node.PubKeyBytes[:]) {
|
||||
@ -287,7 +273,7 @@ func (r *mockGraphSource) FetchLightningNode(
|
||||
}
|
||||
}
|
||||
|
||||
return nil, channeldb.ErrGraphNodeNotFound
|
||||
return nil, graphdb.ErrGraphNodeNotFound
|
||||
}
|
||||
|
||||
// IsStaleNode returns true if the graph source has a node announcement for the
|
||||
@ -733,10 +719,7 @@ func createTestCtx(t *testing.T, startHeight uint32, isChanPeer bool) (
|
||||
notifier := newMockNotifier()
|
||||
router := newMockRouter(startHeight)
|
||||
|
||||
db, err := makeTestDB(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db := channeldb.OpenForTesting(t, t.TempDir())
|
||||
|
||||
waitingProofStore, err := channeldb.NewWaitingProofStore(db)
|
||||
if err != nil {
|
||||
@ -2319,9 +2302,7 @@ func TestProcessZombieEdgeNowLive(t *testing.T) {
|
||||
|
||||
// At this point, the channel should still be considered a zombie.
|
||||
_, _, _, err = ctx.router.GetChannelByID(chanID)
|
||||
if err != channeldb.ErrZombieEdge {
|
||||
t.Fatalf("channel should still be a zombie")
|
||||
}
|
||||
require.ErrorIs(t, err, graphdb.ErrZombieEdge)
|
||||
|
||||
// Attempting to process the current channel update should fail due to
|
||||
// its edge being considered a zombie and its timestamp not being within
|
||||
@ -2442,7 +2423,7 @@ func TestReceiveRemoteChannelUpdateFirst(t *testing.T) {
|
||||
// to the map of premature ChannelUpdates. Check that nothing
|
||||
// was added to the graph.
|
||||
chanInfo, e1, e2, err := ctx.router.GetChannelByID(batch.chanUpdAnn1.ShortChannelID)
|
||||
if err != channeldb.ErrEdgeNotFound {
|
||||
if !errors.Is(err, graphdb.ErrEdgeNotFound) {
|
||||
t.Fatalf("Expected ErrEdgeNotFound, got: %v", err)
|
||||
}
|
||||
if chanInfo != nil {
|
||||
@ -3482,7 +3463,6 @@ out:
|
||||
const newTimeLockDelta = 100
|
||||
var edgesToUpdate []EdgeWithInfo
|
||||
err = ctx.router.ForAllOutgoingChannels(func(
|
||||
_ kvdb.RTx,
|
||||
info *models.ChannelEdgeInfo,
|
||||
edge *models.ChannelEdgePolicy) error {
|
||||
|
||||
|
@ -17,19 +17,10 @@ import (
|
||||
func createTestMessageStore(t *testing.T) *MessageStore {
|
||||
t.Helper()
|
||||
|
||||
db, err := channeldb.Open(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open db: %v", err)
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
db.Close()
|
||||
})
|
||||
db := channeldb.OpenForTesting(t, t.TempDir())
|
||||
|
||||
store, err := NewMessageStore(db)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to initialize message store: %v", err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
return store
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/graph"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/lnpeer"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"golang.org/x/time/rate"
|
||||
@ -373,7 +373,7 @@ type GossipSyncer struct {
|
||||
|
||||
// bufferedChanRangeReplies is used in the waitingQueryChanReply to
|
||||
// buffer all the chunked response to our query.
|
||||
bufferedChanRangeReplies []channeldb.ChannelUpdateInfo
|
||||
bufferedChanRangeReplies []graphdb.ChannelUpdateInfo
|
||||
|
||||
// numChanRangeRepliesRcvd is used to track the number of replies
|
||||
// received as part of a QueryChannelRange. This field is primarily used
|
||||
@ -837,7 +837,7 @@ func (g *GossipSyncer) processChanRangeReply(msg *lnwire.ReplyChannelRange) erro
|
||||
g.prevReplyChannelRange = msg
|
||||
|
||||
for i, scid := range msg.ShortChanIDs {
|
||||
info := channeldb.NewChannelUpdateInfo(
|
||||
info := graphdb.NewChannelUpdateInfo(
|
||||
scid, time.Time{}, time.Time{},
|
||||
)
|
||||
|
||||
@ -1115,7 +1115,7 @@ func (g *GossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) erro
|
||||
// this as there's a transport message size limit which we'll need to
|
||||
// adhere to. We also need to make sure all of our replies cover the
|
||||
// expected range of the query.
|
||||
sendReplyForChunk := func(channelChunk []channeldb.ChannelUpdateInfo,
|
||||
sendReplyForChunk := func(channelChunk []graphdb.ChannelUpdateInfo,
|
||||
firstHeight, lastHeight uint32, finalChunk bool) error {
|
||||
|
||||
// The number of blocks contained in the current chunk (the
|
||||
@ -1164,7 +1164,7 @@ func (g *GossipSyncer) replyChanRangeQuery(query *lnwire.QueryChannelRange) erro
|
||||
var (
|
||||
firstHeight = query.FirstBlockHeight
|
||||
lastHeight uint32
|
||||
channelChunk []channeldb.ChannelUpdateInfo
|
||||
channelChunk []graphdb.ChannelUpdateInfo
|
||||
)
|
||||
|
||||
// chunkSize is the maximum number of SCIDs that we can safely put in a
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -42,7 +42,7 @@ type mockChannelGraphTimeSeries struct {
|
||||
horizonReq chan horizonQuery
|
||||
horizonResp chan []lnwire.Message
|
||||
|
||||
filterReq chan []channeldb.ChannelUpdateInfo
|
||||
filterReq chan []graphdb.ChannelUpdateInfo
|
||||
filterResp chan []lnwire.ShortChannelID
|
||||
|
||||
filterRangeReqs chan filterRangeReq
|
||||
@ -64,7 +64,7 @@ func newMockChannelGraphTimeSeries(
|
||||
horizonReq: make(chan horizonQuery, 1),
|
||||
horizonResp: make(chan []lnwire.Message, 1),
|
||||
|
||||
filterReq: make(chan []channeldb.ChannelUpdateInfo, 1),
|
||||
filterReq: make(chan []graphdb.ChannelUpdateInfo, 1),
|
||||
filterResp: make(chan []lnwire.ShortChannelID, 1),
|
||||
|
||||
filterRangeReqs: make(chan filterRangeReq, 1),
|
||||
@ -92,7 +92,7 @@ func (m *mockChannelGraphTimeSeries) UpdatesInHorizon(chain chainhash.Hash,
|
||||
}
|
||||
|
||||
func (m *mockChannelGraphTimeSeries) FilterKnownChanIDs(chain chainhash.Hash,
|
||||
superSet []channeldb.ChannelUpdateInfo,
|
||||
superSet []graphdb.ChannelUpdateInfo,
|
||||
isZombieChan func(time.Time, time.Time) bool) (
|
||||
[]lnwire.ShortChannelID, error) {
|
||||
|
||||
@ -102,16 +102,16 @@ func (m *mockChannelGraphTimeSeries) FilterKnownChanIDs(chain chainhash.Hash,
|
||||
}
|
||||
func (m *mockChannelGraphTimeSeries) FilterChannelRange(chain chainhash.Hash,
|
||||
startHeight, endHeight uint32, withTimestamps bool) (
|
||||
[]channeldb.BlockChannelRange, error) {
|
||||
[]graphdb.BlockChannelRange, error) {
|
||||
|
||||
m.filterRangeReqs <- filterRangeReq{startHeight, endHeight}
|
||||
reply := <-m.filterRangeResp
|
||||
|
||||
channelsPerBlock := make(map[uint32][]channeldb.ChannelUpdateInfo)
|
||||
channelsPerBlock := make(map[uint32][]graphdb.ChannelUpdateInfo)
|
||||
for _, cid := range reply {
|
||||
channelsPerBlock[cid.BlockHeight] = append(
|
||||
channelsPerBlock[cid.BlockHeight],
|
||||
channeldb.ChannelUpdateInfo{
|
||||
graphdb.ChannelUpdateInfo{
|
||||
ShortChannelID: cid,
|
||||
},
|
||||
)
|
||||
@ -127,11 +127,11 @@ func (m *mockChannelGraphTimeSeries) FilterChannelRange(chain chainhash.Hash,
|
||||
})
|
||||
|
||||
channelRanges := make(
|
||||
[]channeldb.BlockChannelRange, 0, len(channelsPerBlock),
|
||||
[]graphdb.BlockChannelRange, 0, len(channelsPerBlock),
|
||||
)
|
||||
for _, block := range blocks {
|
||||
channelRanges = append(
|
||||
channelRanges, channeldb.BlockChannelRange{
|
||||
channelRanges, graphdb.BlockChannelRange{
|
||||
Height: block,
|
||||
Channels: channelsPerBlock[block],
|
||||
},
|
||||
|
@ -200,6 +200,10 @@ The underlying functionality between those two options remain the same.
|
||||
|
||||
## Code Health
|
||||
|
||||
* A code refactor that [moves all the graph related DB code out of the
|
||||
`channeldb` package](https://github.com/lightningnetwork/lnd/pull/9236) and
|
||||
into the `graph/db` package.
|
||||
|
||||
## Tooling and Documentation
|
||||
|
||||
* [Improved `lncli create` command help text](https://github.com/lightningnetwork/lnd/pull/9077)
|
||||
|
@ -22,10 +22,10 @@ import (
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/chanacceptor"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/discovery"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/labels"
|
||||
|
@ -25,10 +25,10 @@ import (
|
||||
"github.com/lightningnetwork/lnd/chainreg"
|
||||
acpt "github.com/lightningnetwork/lnd/chanacceptor"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/channelnotifier"
|
||||
"github.com/lightningnetwork/lnd/discovery"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lncfg"
|
||||
@ -427,10 +427,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
|
||||
}
|
||||
|
||||
dbDir := filepath.Join(tempTestDir, "cdb")
|
||||
fullDB, err := channeldb.Open(dbDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fullDB := channeldb.OpenForTesting(t, dbDir)
|
||||
|
||||
cdb := fullDB.ChannelStateDB()
|
||||
|
||||
|
@ -16,9 +16,9 @@ import (
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/batch"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnutils"
|
||||
@ -201,10 +201,10 @@ func (b *Builder) Start() error {
|
||||
// then we don't treat this as an explicit error.
|
||||
if _, _, err := b.cfg.Graph.PruneTip(); err != nil {
|
||||
switch {
|
||||
case errors.Is(err, channeldb.ErrGraphNeverPruned):
|
||||
case errors.Is(err, graphdb.ErrGraphNeverPruned):
|
||||
fallthrough
|
||||
|
||||
case errors.Is(err, channeldb.ErrGraphNotFound):
|
||||
case errors.Is(err, graphdb.ErrGraphNotFound):
|
||||
// If the graph has never been pruned, then we'll set
|
||||
// the prune height to the current best height of the
|
||||
// chain backend.
|
||||
@ -256,7 +256,7 @@ func (b *Builder) Start() error {
|
||||
// been applied.
|
||||
channelView, err := b.cfg.Graph.ChannelView()
|
||||
if err != nil && !errors.Is(
|
||||
err, channeldb.ErrGraphNoEdgesFound,
|
||||
err, graphdb.ErrGraphNoEdgesFound,
|
||||
) {
|
||||
|
||||
return err
|
||||
@ -294,7 +294,7 @@ func (b *Builder) Start() error {
|
||||
// of "useful" nodes.
|
||||
err = b.cfg.Graph.PruneGraphNodes()
|
||||
if err != nil &&
|
||||
!errors.Is(err, channeldb.ErrGraphNodesNotFound) {
|
||||
!errors.Is(err, graphdb.ErrGraphNodesNotFound) {
|
||||
|
||||
return err
|
||||
}
|
||||
@ -352,8 +352,8 @@ func (b *Builder) syncGraphWithChain() error {
|
||||
switch {
|
||||
// If the graph has never been pruned, or hasn't fully been
|
||||
// created yet, then we don't treat this as an explicit error.
|
||||
case errors.Is(err, channeldb.ErrGraphNeverPruned):
|
||||
case errors.Is(err, channeldb.ErrGraphNotFound):
|
||||
case errors.Is(err, graphdb.ErrGraphNeverPruned):
|
||||
case errors.Is(err, graphdb.ErrGraphNotFound):
|
||||
default:
|
||||
return err
|
||||
}
|
||||
@ -400,10 +400,10 @@ func (b *Builder) syncGraphWithChain() error {
|
||||
// as this entails we are back to the point where it hasn't seen
|
||||
// any block or created channels, alas there's nothing left to
|
||||
// prune.
|
||||
case errors.Is(err, channeldb.ErrGraphNeverPruned):
|
||||
case errors.Is(err, graphdb.ErrGraphNeverPruned):
|
||||
return nil
|
||||
|
||||
case errors.Is(err, channeldb.ErrGraphNotFound):
|
||||
case errors.Is(err, graphdb.ErrGraphNotFound):
|
||||
return nil
|
||||
|
||||
case err != nil:
|
||||
@ -658,7 +658,7 @@ func (b *Builder) pruneZombieChans() error {
|
||||
// With the channels pruned, we'll also attempt to prune any nodes that
|
||||
// were a part of them.
|
||||
err = b.cfg.Graph.PruneGraphNodes()
|
||||
if err != nil && !errors.Is(err, channeldb.ErrGraphNodesNotFound) {
|
||||
if err != nil && !errors.Is(err, graphdb.ErrGraphNodesNotFound) {
|
||||
return fmt.Errorf("unable to prune graph nodes: %w", err)
|
||||
}
|
||||
|
||||
@ -1165,7 +1165,7 @@ func (b *Builder) processUpdate(msg interface{},
|
||||
op ...batch.SchedulerOption) error {
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case *channeldb.LightningNode:
|
||||
case *models.LightningNode:
|
||||
// Before we add the node to the database, we'll check to see
|
||||
// if the announcement is "fresh" or not. If it isn't, then
|
||||
// we'll return an error.
|
||||
@ -1192,7 +1192,7 @@ func (b *Builder) processUpdate(msg interface{},
|
||||
msg.ChannelID,
|
||||
)
|
||||
if err != nil &&
|
||||
!errors.Is(err, channeldb.ErrGraphNoEdgesFound) {
|
||||
!errors.Is(err, graphdb.ErrGraphNoEdgesFound) {
|
||||
|
||||
return errors.Errorf("unable to check for edge "+
|
||||
"existence: %v", err)
|
||||
@ -1344,7 +1344,7 @@ func (b *Builder) processUpdate(msg interface{},
|
||||
// update the current UTXO filter within our active
|
||||
// FilteredChainView so we are notified if/when this channel is
|
||||
// closed.
|
||||
filterUpdate := []channeldb.EdgePoint{
|
||||
filterUpdate := []graphdb.EdgePoint{
|
||||
{
|
||||
FundingPkScript: fundingPkScript,
|
||||
OutPoint: *fundingPoint,
|
||||
@ -1371,7 +1371,7 @@ func (b *Builder) processUpdate(msg interface{},
|
||||
edge1Timestamp, edge2Timestamp, exists, isZombie, err :=
|
||||
b.cfg.Graph.HasChannelEdge(msg.ChannelID)
|
||||
if err != nil && !errors.Is(
|
||||
err, channeldb.ErrGraphNoEdgesFound,
|
||||
err, graphdb.ErrGraphNoEdgesFound,
|
||||
) {
|
||||
|
||||
return errors.Errorf("unable to check for edge "+
|
||||
@ -1517,7 +1517,7 @@ func (b *Builder) ApplyChannelUpdate(msg *lnwire.ChannelUpdate1) bool {
|
||||
// be ignored.
|
||||
//
|
||||
// NOTE: This method is part of the ChannelGraphSource interface.
|
||||
func (b *Builder) AddNode(node *channeldb.LightningNode,
|
||||
func (b *Builder) AddNode(node *models.LightningNode,
|
||||
op ...batch.SchedulerOption) error {
|
||||
|
||||
rMsg := &routingMsg{
|
||||
@ -1619,12 +1619,12 @@ func (b *Builder) GetChannelByID(chanID lnwire.ShortChannelID) (
|
||||
}
|
||||
|
||||
// FetchLightningNode attempts to look up a target node by its identity public
|
||||
// key. channeldb.ErrGraphNodeNotFound is returned if the node doesn't exist
|
||||
// key. graphdb.ErrGraphNodeNotFound is returned if the node doesn't exist
|
||||
// within the graph.
|
||||
//
|
||||
// NOTE: This method is part of the ChannelGraphSource interface.
|
||||
func (b *Builder) FetchLightningNode(
|
||||
node route.Vertex) (*channeldb.LightningNode, error) {
|
||||
node route.Vertex) (*models.LightningNode, error) {
|
||||
|
||||
return b.cfg.Graph.FetchLightningNode(node)
|
||||
}
|
||||
@ -1633,10 +1633,10 @@ func (b *Builder) FetchLightningNode(
|
||||
//
|
||||
// NOTE: This method is part of the ChannelGraphSource interface.
|
||||
func (b *Builder) ForEachNode(
|
||||
cb func(*channeldb.LightningNode) error) error {
|
||||
cb func(*models.LightningNode) error) error {
|
||||
|
||||
return b.cfg.Graph.ForEachNode(
|
||||
func(_ kvdb.RTx, n *channeldb.LightningNode) error {
|
||||
func(_ kvdb.RTx, n *models.LightningNode) error {
|
||||
return cb(n)
|
||||
})
|
||||
}
|
||||
@ -1645,11 +1645,11 @@ func (b *Builder) ForEachNode(
|
||||
// the router.
|
||||
//
|
||||
// NOTE: This method is part of the ChannelGraphSource interface.
|
||||
func (b *Builder) ForAllOutgoingChannels(cb func(kvdb.RTx,
|
||||
*models.ChannelEdgeInfo, *models.ChannelEdgePolicy) error) error {
|
||||
func (b *Builder) ForAllOutgoingChannels(cb func(*models.ChannelEdgeInfo,
|
||||
*models.ChannelEdgePolicy) error) error {
|
||||
|
||||
return b.cfg.Graph.ForEachNodeChannel(b.cfg.SelfNode,
|
||||
func(tx kvdb.RTx, c *models.ChannelEdgeInfo,
|
||||
func(_ kvdb.RTx, c *models.ChannelEdgeInfo,
|
||||
e *models.ChannelEdgePolicy,
|
||||
_ *models.ChannelEdgePolicy) error {
|
||||
|
||||
@ -1658,7 +1658,7 @@ func (b *Builder) ForAllOutgoingChannels(cb func(kvdb.RTx,
|
||||
"has no policy")
|
||||
}
|
||||
|
||||
return cb(tx, c, e)
|
||||
return cb(c, e)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
@ -93,7 +93,7 @@ func TestIgnoreNodeAnnouncement(t *testing.T) {
|
||||
ctx := createTestCtxFromFile(t, startingBlockHeight, basicGraphFilePath)
|
||||
|
||||
pub := priv1.PubKey()
|
||||
node := &channeldb.LightningNode{
|
||||
node := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
LastUpdate: time.Unix(123, 0),
|
||||
Addresses: testAddrs,
|
||||
@ -1038,7 +1038,7 @@ func TestIsStaleNode(t *testing.T) {
|
||||
|
||||
// With the node stub in the database, we'll add the fully node
|
||||
// announcement to the database.
|
||||
n1 := &channeldb.LightningNode{
|
||||
n1 := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
LastUpdate: updateTimeStamp,
|
||||
Addresses: testAddrs,
|
||||
@ -1453,7 +1453,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) (
|
||||
privKeyMap := make(map[string]*btcec.PrivateKey)
|
||||
channelIDs := make(map[route.Vertex]map[route.Vertex]uint64)
|
||||
links := make(map[lnwire.ShortChannelID]htlcswitch.ChannelLink)
|
||||
var source *channeldb.LightningNode
|
||||
var source *models.LightningNode
|
||||
|
||||
// First we insert all the nodes within the graph as vertexes.
|
||||
for _, node := range g.Nodes {
|
||||
@ -1462,7 +1462,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dbNode := &channeldb.LightningNode{
|
||||
dbNode := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
AuthSigBytes: testSig.Serialize(),
|
||||
LastUpdate: testTime,
|
||||
@ -1593,10 +1593,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) (
|
||||
}
|
||||
|
||||
err = graph.AddChannelEdge(&edgeInfo)
|
||||
if err != nil && !errors.Is(
|
||||
err, channeldb.ErrEdgeAlreadyExist,
|
||||
) {
|
||||
|
||||
if err != nil && !errors.Is(err, graphdb.ErrEdgeAlreadyExist) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -1753,7 +1750,7 @@ func asymmetricTestChannel(alias1, alias2 string, capacity btcutil.Amount,
|
||||
|
||||
// assertChannelsPruned ensures that only the given channels are pruned from the
|
||||
// graph out of the set of all channels.
|
||||
func assertChannelsPruned(t *testing.T, graph *channeldb.ChannelGraph,
|
||||
func assertChannelsPruned(t *testing.T, graph *graphdb.ChannelGraph,
|
||||
channels []*testChannel, prunedChanIDs ...uint64) {
|
||||
|
||||
t.Helper()
|
||||
@ -1835,7 +1832,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool,
|
||||
|
||||
nodeIndex := byte(0)
|
||||
addNodeWithAlias := func(alias string, features *lnwire.FeatureVector) (
|
||||
*channeldb.LightningNode, error) {
|
||||
*models.LightningNode, error) {
|
||||
|
||||
keyBytes := []byte{
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@ -1850,7 +1847,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool,
|
||||
features = lnwire.EmptyFeatureVector()
|
||||
}
|
||||
|
||||
dbNode := &channeldb.LightningNode{
|
||||
dbNode := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
AuthSigBytes: testSig.Serialize(),
|
||||
LastUpdate: testTime,
|
||||
@ -1959,7 +1956,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool,
|
||||
|
||||
err = graph.AddChannelEdge(&edgeInfo)
|
||||
if err != nil &&
|
||||
!errors.Is(err, channeldb.ErrEdgeAlreadyExist) {
|
||||
!errors.Is(err, graphdb.ErrEdgeAlreadyExist) {
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package channeldb
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
@ -121,10 +121,10 @@ func encodeOnionAddr(w io.Writer, addr *tor.OnionAddr) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// deserializeAddr reads the serialized raw representation of an address and
|
||||
// DeserializeAddr reads the serialized raw representation of an address and
|
||||
// deserializes it into the actual address. This allows us to avoid address
|
||||
// resolution within the channeldb package.
|
||||
func deserializeAddr(r io.Reader) (net.Addr, error) {
|
||||
func DeserializeAddr(r io.Reader) (net.Addr, error) {
|
||||
var addrType [1]byte
|
||||
if _, err := r.Read(addrType[:]); err != nil {
|
||||
return nil, err
|
||||
@ -207,9 +207,9 @@ func deserializeAddr(r io.Reader) (net.Addr, error) {
|
||||
return address, nil
|
||||
}
|
||||
|
||||
// serializeAddr serializes an address into its raw bytes representation so that
|
||||
// SerializeAddr serializes an address into its raw bytes representation so that
|
||||
// it can be deserialized without requiring address resolution.
|
||||
func serializeAddr(w io.Writer, address net.Addr) error {
|
||||
func SerializeAddr(w io.Writer, address net.Addr) error {
|
||||
switch addr := address.(type) {
|
||||
case *net.TCPAddr:
|
||||
return encodeTCPAddr(w, addr)
|
@ -1,4 +1,4 @@
|
||||
package channeldb
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -117,7 +117,7 @@ func TestAddrSerialization(t *testing.T) {
|
||||
|
||||
var b bytes.Buffer
|
||||
for _, test := range addrTests {
|
||||
err := serializeAddr(&b, test.expAddr)
|
||||
err := SerializeAddr(&b, test.expAddr)
|
||||
switch {
|
||||
case err == nil && test.serErr != "":
|
||||
t.Fatalf("expected serialization err for addr %v",
|
||||
@ -136,7 +136,7 @@ func TestAddrSerialization(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
addr, err := deserializeAddr(&b)
|
||||
addr, err := DeserializeAddr(&b)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to deserialize address: %v", err)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package channeldb
|
||||
package graphdb
|
||||
|
||||
// channelCache is an in-memory cache used to improve the performance of
|
||||
// ChanUpdatesInHorizon. It caches the chan info and edge policies for a
|
@ -1,10 +1,10 @@
|
||||
package channeldb
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
)
|
||||
|
||||
// TestChannelCache checks the behavior of the channelCache with respect to
|
39
graph/db/codec.go
Normal file
39
graph/db/codec.go
Normal file
@ -0,0 +1,39 @@
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
var (
|
||||
// byteOrder defines the preferred byte order, which is Big Endian.
|
||||
byteOrder = binary.BigEndian
|
||||
)
|
||||
|
||||
// WriteOutpoint writes an outpoint to the passed writer using the minimal
|
||||
// amount of bytes possible.
|
||||
func WriteOutpoint(w io.Writer, o *wire.OutPoint) error {
|
||||
if _, err := w.Write(o.Hash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(w, byteOrder, o.Index); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadOutpoint reads an outpoint from the passed reader that was previously
|
||||
// written using the WriteOutpoint struct.
|
||||
func ReadOutpoint(r io.Reader, o *wire.OutPoint) error {
|
||||
if _, err := io.ReadFull(r, o.Hash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(r, byteOrder, &o.Index); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
75
graph/db/errors.go
Normal file
75
graph/db/errors.go
Normal file
@ -0,0 +1,75 @@
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrEdgePolicyOptionalFieldNotFound is an error returned if a channel
|
||||
// policy field is not found in the db even though its message flags
|
||||
// indicate it should be.
|
||||
ErrEdgePolicyOptionalFieldNotFound = fmt.Errorf("optional field not " +
|
||||
"present")
|
||||
|
||||
// ErrGraphNotFound is returned when at least one of the components of
|
||||
// graph doesn't exist.
|
||||
ErrGraphNotFound = fmt.Errorf("graph bucket not initialized")
|
||||
|
||||
// ErrGraphNeverPruned is returned when graph was never pruned.
|
||||
ErrGraphNeverPruned = fmt.Errorf("graph never pruned")
|
||||
|
||||
// ErrSourceNodeNotSet is returned if the source node of the graph
|
||||
// hasn't been added The source node is the center node within a
|
||||
// star-graph.
|
||||
ErrSourceNodeNotSet = fmt.Errorf("source node does not exist")
|
||||
|
||||
// ErrGraphNodesNotFound is returned in case none of the nodes has
|
||||
// been added in graph node bucket.
|
||||
ErrGraphNodesNotFound = fmt.Errorf("no graph nodes exist")
|
||||
|
||||
// ErrGraphNoEdgesFound is returned in case of none of the channel/edges
|
||||
// has been added in graph edge bucket.
|
||||
ErrGraphNoEdgesFound = fmt.Errorf("no graph edges exist")
|
||||
|
||||
// ErrGraphNodeNotFound is returned when we're unable to find the target
|
||||
// node.
|
||||
ErrGraphNodeNotFound = fmt.Errorf("unable to find node")
|
||||
|
||||
// ErrZombieEdge is an error returned when we attempt to look up an edge
|
||||
// but it is marked as a zombie within the zombie index.
|
||||
ErrZombieEdge = errors.New("edge marked as zombie")
|
||||
|
||||
// ErrEdgeNotFound is returned when an edge for the target chanID
|
||||
// can't be found.
|
||||
ErrEdgeNotFound = fmt.Errorf("edge not found")
|
||||
|
||||
// ErrEdgeAlreadyExist is returned when edge with specific
|
||||
// channel id can't be added because it already exist.
|
||||
ErrEdgeAlreadyExist = fmt.Errorf("edge already exist")
|
||||
|
||||
// ErrNodeAliasNotFound is returned when alias for node can't be found.
|
||||
ErrNodeAliasNotFound = fmt.Errorf("alias for node not found")
|
||||
|
||||
// ErrClosedScidsNotFound is returned when the closed scid bucket
|
||||
// hasn't been created.
|
||||
ErrClosedScidsNotFound = fmt.Errorf("closed scid bucket doesn't exist")
|
||||
|
||||
// ErrZombieEdgeNotFound is an error returned when we attempt to find an
|
||||
// edge in the zombie index which is not there.
|
||||
ErrZombieEdgeNotFound = errors.New("edge not found in zombie index")
|
||||
|
||||
// ErrUnknownAddressType is returned when a node's addressType is not
|
||||
// an expected value.
|
||||
ErrUnknownAddressType = fmt.Errorf("address type cannot be resolved")
|
||||
)
|
||||
|
||||
// ErrTooManyExtraOpaqueBytes creates an error which should be returned if the
|
||||
// caller attempts to write an announcement message which bares too many extra
|
||||
// opaque bytes. We limit this value in order to ensure that we don't waste
|
||||
// disk space due to nodes unnecessarily padding out their announcements with
|
||||
// garbage data.
|
||||
func ErrTooManyExtraOpaqueBytes(numBytes int) error {
|
||||
return fmt.Errorf("max allowed number of opaque bytes is %v, received "+
|
||||
"%v bytes", MaxAllowedExtraOpaqueBytes, numBytes)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package channeldb
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -6,22 +6,21 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
"sort"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/aliasmgr"
|
||||
"github.com/lightningnetwork/lnd/batch"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
@ -124,9 +123,9 @@ var (
|
||||
// edge's participants.
|
||||
zombieBucket = []byte("zombie-index")
|
||||
|
||||
// disabledEdgePolicyBucket is a sub-bucket of the main edgeBucket bucket
|
||||
// responsible for maintaining an index of disabled edge policies. Each
|
||||
// entry exists within the bucket as follows:
|
||||
// disabledEdgePolicyBucket is a sub-bucket of the main edgeBucket
|
||||
// bucket responsible for maintaining an index of disabled edge
|
||||
// policies. Each entry exists within the bucket as follows:
|
||||
//
|
||||
// maps: <chanID><direction> -> []byte{}
|
||||
//
|
||||
@ -198,11 +197,15 @@ type ChannelGraph struct {
|
||||
|
||||
// NewChannelGraph allocates a new ChannelGraph backed by a DB instance. The
|
||||
// returned instance has its own unique reject cache and channel cache.
|
||||
func NewChannelGraph(db kvdb.Backend, rejectCacheSize, chanCacheSize int,
|
||||
batchCommitInterval time.Duration, preAllocCacheNumNodes int,
|
||||
useGraphCache, noMigrations bool) (*ChannelGraph, error) {
|
||||
func NewChannelGraph(db kvdb.Backend, options ...OptionModifier) (*ChannelGraph,
|
||||
error) {
|
||||
|
||||
if !noMigrations {
|
||||
opts := DefaultOptions()
|
||||
for _, o := range options {
|
||||
o(opts)
|
||||
}
|
||||
|
||||
if !opts.NoMigration {
|
||||
if err := initChannelGraph(db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -210,20 +213,20 @@ func NewChannelGraph(db kvdb.Backend, rejectCacheSize, chanCacheSize int,
|
||||
|
||||
g := &ChannelGraph{
|
||||
db: db,
|
||||
rejectCache: newRejectCache(rejectCacheSize),
|
||||
chanCache: newChannelCache(chanCacheSize),
|
||||
rejectCache: newRejectCache(opts.RejectCacheSize),
|
||||
chanCache: newChannelCache(opts.ChannelCacheSize),
|
||||
}
|
||||
g.chanScheduler = batch.NewTimeScheduler(
|
||||
db, &g.cacheMu, batchCommitInterval,
|
||||
db, &g.cacheMu, opts.BatchCommitInterval,
|
||||
)
|
||||
g.nodeScheduler = batch.NewTimeScheduler(
|
||||
db, nil, batchCommitInterval,
|
||||
db, nil, opts.BatchCommitInterval,
|
||||
)
|
||||
|
||||
// The graph cache can be turned off (e.g. for mobile users) for a
|
||||
// speed/memory usage tradeoff.
|
||||
if useGraphCache {
|
||||
g.graphCache = NewGraphCache(preAllocCacheNumNodes)
|
||||
if opts.UseGraphCache {
|
||||
g.graphCache = NewGraphCache(opts.PreAllocCacheNumNodes)
|
||||
startTime := time.Now()
|
||||
log.Debugf("Populating in-memory channel graph, this might " +
|
||||
"take a while...")
|
||||
@ -349,7 +352,7 @@ func (c *ChannelGraph) Wipe() error {
|
||||
return initChannelGraph(c.db)
|
||||
}
|
||||
|
||||
// createChannelDB creates and initializes a fresh version of channeldb. In
|
||||
// createChannelDB creates and initializes a fresh version of In
|
||||
// the case that the target path has not yet been created or doesn't yet exist,
|
||||
// then the path is created. Additionally, all required top-level buckets used
|
||||
// within the database are created.
|
||||
@ -410,6 +413,32 @@ func (c *ChannelGraph) NewPathFindTx() (kvdb.RTx, error) {
|
||||
return c.db.BeginReadTx()
|
||||
}
|
||||
|
||||
// AddrsForNode returns all known addresses for the target node public key that
|
||||
// the graph DB is aware of. The returned boolean indicates if the given node is
|
||||
// unknown to the graph DB or not.
|
||||
//
|
||||
// NOTE: this is part of the channeldb.AddrSource interface.
|
||||
func (c *ChannelGraph) AddrsForNode(nodePub *btcec.PublicKey) (bool, []net.Addr,
|
||||
error) {
|
||||
|
||||
pubKey, err := route.NewVertexFromBytes(nodePub.SerializeCompressed())
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
node, err := c.FetchLightningNode(pubKey)
|
||||
// We don't consider it an error if the graph is unaware of the node.
|
||||
switch {
|
||||
case err != nil && !errors.Is(err, ErrGraphNodeNotFound):
|
||||
return false, nil, err
|
||||
|
||||
case errors.Is(err, ErrGraphNodeNotFound):
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
return true, node.Addresses, nil
|
||||
}
|
||||
|
||||
// ForEachChannel iterates through all the channel edges stored within the
|
||||
// graph and invokes the passed callback for each edge. The callback takes two
|
||||
// edges as since this is a directed graph, both the in/out edges are visited.
|
||||
@ -442,28 +471,32 @@ func (c *ChannelGraph) ForEachChannel(cb func(*models.ChannelEdgeInfo,
|
||||
|
||||
// Load edge index, recombine each channel with the policies
|
||||
// loaded above and invoke the callback.
|
||||
return kvdb.ForAll(edgeIndex, func(k, edgeInfoBytes []byte) error {
|
||||
var chanID [8]byte
|
||||
copy(chanID[:], k)
|
||||
return kvdb.ForAll(
|
||||
edgeIndex, func(k, edgeInfoBytes []byte) error {
|
||||
var chanID [8]byte
|
||||
copy(chanID[:], k)
|
||||
|
||||
edgeInfoReader := bytes.NewReader(edgeInfoBytes)
|
||||
info, err := deserializeChanEdgeInfo(edgeInfoReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
edgeInfoReader := bytes.NewReader(edgeInfoBytes)
|
||||
info, err := deserializeChanEdgeInfo(
|
||||
edgeInfoReader,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
policy1 := channelMap[channelMapKey{
|
||||
nodeKey: info.NodeKey1Bytes,
|
||||
chanID: chanID,
|
||||
}]
|
||||
policy1 := channelMap[channelMapKey{
|
||||
nodeKey: info.NodeKey1Bytes,
|
||||
chanID: chanID,
|
||||
}]
|
||||
|
||||
policy2 := channelMap[channelMapKey{
|
||||
nodeKey: info.NodeKey2Bytes,
|
||||
chanID: chanID,
|
||||
}]
|
||||
policy2 := channelMap[channelMapKey{
|
||||
nodeKey: info.NodeKey2Bytes,
|
||||
chanID: chanID,
|
||||
}]
|
||||
|
||||
return cb(&info, policy1, policy2)
|
||||
})
|
||||
return cb(&info, policy1, policy2)
|
||||
},
|
||||
)
|
||||
}, func() {})
|
||||
}
|
||||
|
||||
@ -571,7 +604,9 @@ func (c *ChannelGraph) ForEachNodeCached(cb func(node route.Vertex,
|
||||
// We'll iterate over each node, then the set of channels for each
|
||||
// node, and construct a similar callback functiopn signature as the
|
||||
// main funcotin expects.
|
||||
return c.ForEachNode(func(tx kvdb.RTx, node *LightningNode) error {
|
||||
return c.ForEachNode(func(tx kvdb.RTx,
|
||||
node *models.LightningNode) error {
|
||||
|
||||
channels := make(map[uint64]*DirectedChannel)
|
||||
|
||||
err := c.ForEachNodeChannelTx(tx, node.PubKeyBytes,
|
||||
@ -646,20 +681,27 @@ func (c *ChannelGraph) DisabledChannelIDs() ([]uint64, error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// We iterate over all disabled policies and we add each channel that
|
||||
// has more than one disabled policy to disabledChanIDs array.
|
||||
return disabledEdgePolicyIndex.ForEach(func(k, v []byte) error {
|
||||
chanID := byteOrder.Uint64(k[:8])
|
||||
_, edgeFound := chanEdgeFound[chanID]
|
||||
if edgeFound {
|
||||
delete(chanEdgeFound, chanID)
|
||||
disabledChanIDs = append(disabledChanIDs, chanID)
|
||||
return nil
|
||||
}
|
||||
// We iterate over all disabled policies and we add each channel
|
||||
// that has more than one disabled policy to disabledChanIDs
|
||||
// array.
|
||||
return disabledEdgePolicyIndex.ForEach(
|
||||
func(k, v []byte) error {
|
||||
chanID := byteOrder.Uint64(k[:8])
|
||||
_, edgeFound := chanEdgeFound[chanID]
|
||||
if edgeFound {
|
||||
delete(chanEdgeFound, chanID)
|
||||
disabledChanIDs = append(
|
||||
disabledChanIDs, chanID,
|
||||
)
|
||||
|
||||
chanEdgeFound[chanID] = struct{}{}
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
chanEdgeFound[chanID] = struct{}{}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}, func() {
|
||||
disabledChanIDs = nil
|
||||
chanEdgeFound = make(map[uint64]struct{})
|
||||
@ -679,7 +721,7 @@ func (c *ChannelGraph) DisabledChannelIDs() ([]uint64, error) {
|
||||
// TODO(roasbeef): add iterator interface to allow for memory efficient graph
|
||||
// traversal when graph gets mega
|
||||
func (c *ChannelGraph) ForEachNode(
|
||||
cb func(kvdb.RTx, *LightningNode) error) error {
|
||||
cb func(kvdb.RTx, *models.LightningNode) error) error {
|
||||
|
||||
traversal := func(tx kvdb.RTx) error {
|
||||
// First grab the nodes bucket which stores the mapping from
|
||||
@ -756,8 +798,8 @@ func (c *ChannelGraph) ForEachNodeCacheable(cb func(kvdb.RTx,
|
||||
// as the center node within a star-graph. This method may be used to kick off
|
||||
// a path finding algorithm in order to explore the reachability of another
|
||||
// node based off the source node.
|
||||
func (c *ChannelGraph) SourceNode() (*LightningNode, error) {
|
||||
var source *LightningNode
|
||||
func (c *ChannelGraph) SourceNode() (*models.LightningNode, error) {
|
||||
var source *models.LightningNode
|
||||
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
||||
// First grab the nodes bucket which stores the mapping from
|
||||
// pubKey to node information.
|
||||
@ -787,7 +829,9 @@ func (c *ChannelGraph) SourceNode() (*LightningNode, error) {
|
||||
// of the graph. The source node is treated as the center node within a
|
||||
// star-graph. This method may be used to kick off a path finding algorithm in
|
||||
// order to explore the reachability of another node based off the source node.
|
||||
func (c *ChannelGraph) sourceNode(nodes kvdb.RBucket) (*LightningNode, error) {
|
||||
func (c *ChannelGraph) sourceNode(nodes kvdb.RBucket) (*models.LightningNode,
|
||||
error) {
|
||||
|
||||
selfPub := nodes.Get(sourceKey)
|
||||
if selfPub == nil {
|
||||
return nil, ErrSourceNodeNotSet
|
||||
@ -806,7 +850,7 @@ func (c *ChannelGraph) sourceNode(nodes kvdb.RBucket) (*LightningNode, error) {
|
||||
// SetSourceNode sets the source node within the graph database. The source
|
||||
// node is to be used as the center of a star-graph within path finding
|
||||
// algorithms.
|
||||
func (c *ChannelGraph) SetSourceNode(node *LightningNode) error {
|
||||
func (c *ChannelGraph) SetSourceNode(node *models.LightningNode) error {
|
||||
nodePubBytes := node.PubKeyBytes[:]
|
||||
|
||||
return kvdb.Update(c.db, func(tx kvdb.RwTx) error {
|
||||
@ -837,7 +881,7 @@ func (c *ChannelGraph) SetSourceNode(node *LightningNode) error {
|
||||
// channel update.
|
||||
//
|
||||
// TODO(roasbeef): also need sig of announcement
|
||||
func (c *ChannelGraph) AddLightningNode(node *LightningNode,
|
||||
func (c *ChannelGraph) AddLightningNode(node *models.LightningNode,
|
||||
op ...batch.SchedulerOption) error {
|
||||
|
||||
r := &batch.Request{
|
||||
@ -863,7 +907,7 @@ func (c *ChannelGraph) AddLightningNode(node *LightningNode,
|
||||
return c.nodeScheduler.Execute(r)
|
||||
}
|
||||
|
||||
func addLightningNode(tx kvdb.RwTx, node *LightningNode) error {
|
||||
func addLightningNode(tx kvdb.RwTx, node *models.LightningNode) error {
|
||||
nodes, err := tx.CreateTopLevelBucket(nodeBucket)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -1076,7 +1120,7 @@ func (c *ChannelGraph) addChannelEdge(tx kvdb.RwTx,
|
||||
_, node1Err := fetchLightningNode(nodes, edge.NodeKey1Bytes[:])
|
||||
switch {
|
||||
case node1Err == ErrGraphNodeNotFound:
|
||||
node1Shell := LightningNode{
|
||||
node1Shell := models.LightningNode{
|
||||
PubKeyBytes: edge.NodeKey1Bytes,
|
||||
HaveNodeAnnouncement: false,
|
||||
}
|
||||
@ -1092,7 +1136,7 @@ func (c *ChannelGraph) addChannelEdge(tx kvdb.RwTx,
|
||||
_, node2Err := fetchLightningNode(nodes, edge.NodeKey2Bytes[:])
|
||||
switch {
|
||||
case node2Err == ErrGraphNodeNotFound:
|
||||
node2Shell := LightningNode{
|
||||
node2Shell := models.LightningNode{
|
||||
PubKeyBytes: edge.NodeKey2Bytes,
|
||||
HaveNodeAnnouncement: false,
|
||||
}
|
||||
@ -1128,7 +1172,7 @@ func (c *ChannelGraph) addChannelEdge(tx kvdb.RwTx,
|
||||
// Finally we add it to the channel index which maps channel points
|
||||
// (outpoints) to the shorter channel ID's.
|
||||
var b bytes.Buffer
|
||||
if err := writeOutpoint(&b, &edge.ChannelPoint); err != nil {
|
||||
if err := WriteOutpoint(&b, &edge.ChannelPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
return chanIndex.Put(b.Bytes(), chanKey[:])
|
||||
@ -1309,12 +1353,15 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint,
|
||||
return err
|
||||
}
|
||||
|
||||
// Next grab the two edge indexes which will also need to be updated.
|
||||
// Next grab the two edge indexes which will also need to be
|
||||
// updated.
|
||||
edgeIndex, err := edges.CreateBucketIfNotExists(edgeIndexBucket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chanIndex, err := edges.CreateBucketIfNotExists(channelPointBucket)
|
||||
chanIndex, err := edges.CreateBucketIfNotExists(
|
||||
channelPointBucket,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1335,7 +1382,8 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint,
|
||||
// if NOT if filter
|
||||
|
||||
var opBytes bytes.Buffer
|
||||
if err := writeOutpoint(&opBytes, chanPoint); err != nil {
|
||||
err := WriteOutpoint(&opBytes, chanPoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1374,7 +1422,9 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint,
|
||||
return err
|
||||
}
|
||||
|
||||
pruneBucket, err := metaBucket.CreateBucketIfNotExists(pruneLogBucket)
|
||||
pruneBucket, err := metaBucket.CreateBucketIfNotExists(
|
||||
pruneLogBucket,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1520,7 +1570,8 @@ func (c *ChannelGraph) pruneGraphNodes(nodes kvdb.RwBucket,
|
||||
|
||||
// If we reach this point, then there are no longer any edges
|
||||
// that connect this node, so we can delete it.
|
||||
if err := c.deleteLightningNode(nodes, nodePubKey[:]); err != nil {
|
||||
err := c.deleteLightningNode(nodes, nodePubKey[:])
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrGraphNodeNotFound) ||
|
||||
errors.Is(err, ErrGraphNodesNotFound) {
|
||||
|
||||
@ -1587,7 +1638,9 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) (
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chanIndex, err := edges.CreateBucketIfNotExists(channelPointBucket)
|
||||
chanIndex, err := edges.CreateBucketIfNotExists(
|
||||
channelPointBucket,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1635,7 +1688,9 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) (
|
||||
return err
|
||||
}
|
||||
|
||||
pruneBucket, err := metaBucket.CreateBucketIfNotExists(pruneLogBucket)
|
||||
pruneBucket, err := metaBucket.CreateBucketIfNotExists(
|
||||
pruneLogBucket,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1650,9 +1705,9 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) (
|
||||
// the keys in a second loop.
|
||||
var pruneKeys [][]byte
|
||||
pruneCursor := pruneBucket.ReadWriteCursor()
|
||||
//nolint:lll
|
||||
for k, _ := pruneCursor.Seek(pruneKeyStart[:]); k != nil &&
|
||||
bytes.Compare(k, pruneKeyEnd[:]) <= 0; k, _ = pruneCursor.Next() {
|
||||
|
||||
pruneKeys = append(pruneKeys, k)
|
||||
}
|
||||
|
||||
@ -1807,7 +1862,7 @@ func (c *ChannelGraph) ChannelID(chanPoint *wire.OutPoint) (uint64, error) {
|
||||
// getChanID returns the assigned channel ID for a given channel point.
|
||||
func getChanID(tx kvdb.RTx, chanPoint *wire.OutPoint) (uint64, error) {
|
||||
var b bytes.Buffer
|
||||
if err := writeOutpoint(&b, chanPoint); err != nil {
|
||||
if err := WriteOutpoint(&b, chanPoint); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@ -1891,11 +1946,11 @@ type ChannelEdge struct {
|
||||
|
||||
// Node1 is "node 1" in the channel. This is the node that would have
|
||||
// produced Policy1 if it exists.
|
||||
Node1 *LightningNode
|
||||
Node1 *models.LightningNode
|
||||
|
||||
// Node2 is "node 2" in the channel. This is the node that would have
|
||||
// produced Policy2 if it exists.
|
||||
Node2 *LightningNode
|
||||
Node2 *models.LightningNode
|
||||
}
|
||||
|
||||
// ChanUpdatesInHorizon returns all the known channel edges which have at least
|
||||
@ -1948,6 +2003,8 @@ func (c *ChannelGraph) ChanUpdatesInHorizon(startTime,
|
||||
// With our start and end times constructed, we'll step through
|
||||
// the index collecting the info and policy of each update of
|
||||
// each channel that has a last update within the time range.
|
||||
//
|
||||
//nolint:lll
|
||||
for indexKey, _ := updateCursor.Seek(startTimeBytes[:]); indexKey != nil &&
|
||||
bytes.Compare(indexKey, endTimeBytes[:]) <= 0; indexKey, _ = updateCursor.Next() {
|
||||
|
||||
@ -2051,9 +2108,9 @@ func (c *ChannelGraph) ChanUpdatesInHorizon(startTime,
|
||||
// nodes to quickly determine if they have the same set of up to date node
|
||||
// announcements.
|
||||
func (c *ChannelGraph) NodeUpdatesInHorizon(startTime,
|
||||
endTime time.Time) ([]LightningNode, error) {
|
||||
endTime time.Time) ([]models.LightningNode, error) {
|
||||
|
||||
var nodesInHorizon []LightningNode
|
||||
var nodesInHorizon []models.LightningNode
|
||||
|
||||
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
|
||||
nodes := tx.ReadBucket(nodeBucket)
|
||||
@ -2081,6 +2138,8 @@ func (c *ChannelGraph) NodeUpdatesInHorizon(startTime,
|
||||
// With our start and end times constructed, we'll step through
|
||||
// the index collecting info for each node within the time
|
||||
// range.
|
||||
//
|
||||
//nolint:lll
|
||||
for indexKey, _ := updateCursor.Seek(startTimeBytes[:]); indexKey != nil &&
|
||||
bytes.Compare(indexKey, endTimeBytes[:]) <= 0; indexKey, _ = updateCursor.Next() {
|
||||
|
||||
@ -2317,6 +2376,8 @@ func (c *ChannelGraph) FilterChannelRange(startHeight,
|
||||
|
||||
// We'll now iterate through the database, and find each
|
||||
// channel ID that resides within the specified range.
|
||||
//
|
||||
//nolint:lll
|
||||
for k, v := cursor.Seek(chanIDStart[:]); k != nil &&
|
||||
bytes.Compare(k, chanIDEnd[:]) <= 0; k, v = cursor.Next() {
|
||||
// Don't send alias SCIDs during gossip sync.
|
||||
@ -2549,7 +2610,9 @@ func delEdgeUpdateIndexEntry(edgesBucket kvdb.RwBucket, chanID uint64,
|
||||
// would have been created by both edges: we'll alternate the update
|
||||
// times, as one may had overridden the other.
|
||||
if edge1 != nil {
|
||||
byteOrder.PutUint64(indexKey[:8], uint64(edge1.LastUpdate.Unix()))
|
||||
byteOrder.PutUint64(
|
||||
indexKey[:8], uint64(edge1.LastUpdate.Unix()),
|
||||
)
|
||||
if err := updateIndex.Delete(indexKey[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -2558,7 +2621,9 @@ func delEdgeUpdateIndexEntry(edgesBucket kvdb.RwBucket, chanID uint64,
|
||||
// We'll also attempt to delete the entry that may have been created by
|
||||
// the second edge.
|
||||
if edge2 != nil {
|
||||
byteOrder.PutUint64(indexKey[:8], uint64(edge2.LastUpdate.Unix()))
|
||||
byteOrder.PutUint64(
|
||||
indexKey[:8], uint64(edge2.LastUpdate.Unix()),
|
||||
)
|
||||
if err := updateIndex.Delete(indexKey[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -2625,7 +2690,8 @@ func (c *ChannelGraph) delChannelEdgeUnsafe(edges, edgeIndex, chanIndex,
|
||||
}
|
||||
|
||||
// As part of deleting the edge we also remove all disabled entries
|
||||
// from the edgePolicyDisabledIndex bucket. We do that for both directions.
|
||||
// from the edgePolicyDisabledIndex bucket. We do that for both
|
||||
// directions.
|
||||
updateEdgePolicyDisabledIndex(edges, cid, false, false)
|
||||
updateEdgePolicyDisabledIndex(edges, cid, true, false)
|
||||
|
||||
@ -2635,7 +2701,7 @@ func (c *ChannelGraph) delChannelEdgeUnsafe(edges, edgeIndex, chanIndex,
|
||||
return err
|
||||
}
|
||||
var b bytes.Buffer
|
||||
if err := writeOutpoint(&b, &edgeInfo.ChannelPoint); err != nil {
|
||||
if err := WriteOutpoint(&b, &edgeInfo.ChannelPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chanIndex.Delete(b.Bytes()); err != nil {
|
||||
@ -2849,127 +2915,6 @@ func updateEdgePolicy(tx kvdb.RwTx, edge *models.ChannelEdgePolicy,
|
||||
return isUpdate1, nil
|
||||
}
|
||||
|
||||
// LightningNode represents an individual vertex/node within the channel graph.
|
||||
// A node is connected to other nodes by one or more channel edges emanating
|
||||
// from it. As the graph is directed, a node will also have an incoming edge
|
||||
// attached to it for each outgoing edge.
|
||||
type LightningNode struct {
|
||||
// PubKeyBytes is the raw bytes of the public key of the target node.
|
||||
PubKeyBytes [33]byte
|
||||
pubKey *btcec.PublicKey
|
||||
|
||||
// HaveNodeAnnouncement indicates whether we received a node
|
||||
// announcement for this particular node. If true, the remaining fields
|
||||
// will be set, if false only the PubKey is known for this node.
|
||||
HaveNodeAnnouncement bool
|
||||
|
||||
// LastUpdate is the last time the vertex information for this node has
|
||||
// been updated.
|
||||
LastUpdate time.Time
|
||||
|
||||
// Address is the TCP address this node is reachable over.
|
||||
Addresses []net.Addr
|
||||
|
||||
// Color is the selected color for the node.
|
||||
Color color.RGBA
|
||||
|
||||
// Alias is a nick-name for the node. The alias can be used to confirm
|
||||
// a node's identity or to serve as a short ID for an address book.
|
||||
Alias string
|
||||
|
||||
// AuthSigBytes is the raw signature under the advertised public key
|
||||
// which serves to authenticate the attributes announced by this node.
|
||||
AuthSigBytes []byte
|
||||
|
||||
// Features is the list of protocol features supported by this node.
|
||||
Features *lnwire.FeatureVector
|
||||
|
||||
// ExtraOpaqueData is the set of data that was appended to this
|
||||
// message, some of which we may not actually know how to iterate or
|
||||
// parse. By holding onto this data, we ensure that we're able to
|
||||
// properly validate the set of signatures that cover these new fields,
|
||||
// and ensure we're able to make upgrades to the network in a forwards
|
||||
// compatible manner.
|
||||
ExtraOpaqueData []byte
|
||||
|
||||
// TODO(roasbeef): discovery will need storage to keep it's last IP
|
||||
// address and re-announce if interface changes?
|
||||
|
||||
// TODO(roasbeef): add update method and fetch?
|
||||
}
|
||||
|
||||
// PubKey is the node's long-term identity public key. This key will be used to
|
||||
// authenticated any advertisements/updates sent by the node.
|
||||
//
|
||||
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||
// to fully deserialize the pubkey if absolutely necessary.
|
||||
func (l *LightningNode) PubKey() (*btcec.PublicKey, error) {
|
||||
if l.pubKey != nil {
|
||||
return l.pubKey, nil
|
||||
}
|
||||
|
||||
key, err := btcec.ParsePubKey(l.PubKeyBytes[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l.pubKey = key
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// AuthSig is a signature under the advertised public key which serves to
|
||||
// authenticate the attributes announced by this node.
|
||||
//
|
||||
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||
// to fully deserialize the signature if absolutely necessary.
|
||||
func (l *LightningNode) AuthSig() (*ecdsa.Signature, error) {
|
||||
return ecdsa.ParseSignature(l.AuthSigBytes)
|
||||
}
|
||||
|
||||
// AddPubKey is a setter-link method that can be used to swap out the public
|
||||
// key for a node.
|
||||
func (l *LightningNode) AddPubKey(key *btcec.PublicKey) {
|
||||
l.pubKey = key
|
||||
copy(l.PubKeyBytes[:], key.SerializeCompressed())
|
||||
}
|
||||
|
||||
// NodeAnnouncement retrieves the latest node announcement of the node.
|
||||
func (l *LightningNode) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement,
|
||||
error) {
|
||||
|
||||
if !l.HaveNodeAnnouncement {
|
||||
return nil, fmt.Errorf("node does not have node announcement")
|
||||
}
|
||||
|
||||
alias, err := lnwire.NewNodeAlias(l.Alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeAnn := &lnwire.NodeAnnouncement{
|
||||
Features: l.Features.RawFeatureVector,
|
||||
NodeID: l.PubKeyBytes,
|
||||
RGBColor: l.Color,
|
||||
Alias: alias,
|
||||
Addresses: l.Addresses,
|
||||
Timestamp: uint32(l.LastUpdate.Unix()),
|
||||
ExtraOpaqueData: l.ExtraOpaqueData,
|
||||
}
|
||||
|
||||
if !signed {
|
||||
return nodeAnn, nil
|
||||
}
|
||||
|
||||
sig, err := lnwire.NewSigFromECDSARawSignature(l.AuthSigBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeAnn.Signature = sig
|
||||
|
||||
return nodeAnn, nil
|
||||
}
|
||||
|
||||
// isPublic determines whether the node is seen as public within the graph from
|
||||
// the source node's point of view. An existing database transaction can also be
|
||||
// specified.
|
||||
@ -3019,7 +2964,7 @@ func (c *ChannelGraph) isPublic(tx kvdb.RTx, nodePub route.Vertex,
|
||||
// ErrGraphNodeNotFound is returned. An optional transaction may be provided.
|
||||
// If none is provided, then a new one will be created.
|
||||
func (c *ChannelGraph) FetchLightningNodeTx(tx kvdb.RTx, nodePub route.Vertex) (
|
||||
*LightningNode, error) {
|
||||
*models.LightningNode, error) {
|
||||
|
||||
return c.fetchLightningNode(tx, nodePub)
|
||||
}
|
||||
@ -3027,8 +2972,8 @@ func (c *ChannelGraph) FetchLightningNodeTx(tx kvdb.RTx, nodePub route.Vertex) (
|
||||
// FetchLightningNode attempts to look up a target node by its identity public
|
||||
// key. If the node isn't found in the database, then ErrGraphNodeNotFound is
|
||||
// returned.
|
||||
func (c *ChannelGraph) FetchLightningNode(nodePub route.Vertex) (*LightningNode,
|
||||
error) {
|
||||
func (c *ChannelGraph) FetchLightningNode(nodePub route.Vertex) (
|
||||
*models.LightningNode, error) {
|
||||
|
||||
return c.fetchLightningNode(nil, nodePub)
|
||||
}
|
||||
@ -3038,9 +2983,9 @@ func (c *ChannelGraph) FetchLightningNode(nodePub route.Vertex) (*LightningNode,
|
||||
// returned. An optional transaction may be provided. If none is provided, then
|
||||
// a new one will be created.
|
||||
func (c *ChannelGraph) fetchLightningNode(tx kvdb.RTx,
|
||||
nodePub route.Vertex) (*LightningNode, error) {
|
||||
nodePub route.Vertex) (*models.LightningNode, error) {
|
||||
|
||||
var node *LightningNode
|
||||
var node *models.LightningNode
|
||||
fetch := func(tx kvdb.RTx) error {
|
||||
// First grab the nodes bucket which stores the mapping from
|
||||
// pubKey to node information.
|
||||
@ -3139,7 +3084,9 @@ var _ GraphCacheNode = (*graphCacheNode)(nil)
|
||||
// timestamp of when the data for the node was lasted updated is returned along
|
||||
// with a true boolean. Otherwise, an empty time.Time is returned with a false
|
||||
// boolean.
|
||||
func (c *ChannelGraph) HasLightningNode(nodePub [33]byte) (time.Time, bool, error) {
|
||||
func (c *ChannelGraph) HasLightningNode(nodePub [33]byte) (time.Time, bool,
|
||||
error) {
|
||||
|
||||
var (
|
||||
updateTime time.Time
|
||||
exists bool
|
||||
@ -3216,7 +3163,7 @@ func nodeTraversal(tx kvdb.RTx, nodePub []byte, db kvdb.Backend,
|
||||
// as its prefix. This indicates that we've stepped over into
|
||||
// another node's edges, so we can terminate our scan.
|
||||
edgeCursor := edges.ReadCursor()
|
||||
for nodeEdge, _ := edgeCursor.Seek(nodeStart[:]); bytes.HasPrefix(nodeEdge, nodePub); nodeEdge, _ = edgeCursor.Next() {
|
||||
for nodeEdge, _ := edgeCursor.Seek(nodeStart[:]); bytes.HasPrefix(nodeEdge, nodePub); nodeEdge, _ = edgeCursor.Next() { //nolint:lll
|
||||
// If the prefix still matches, the channel id is
|
||||
// returned in nodeEdge. Channel id is used to lookup
|
||||
// the node at the other end of the channel and both
|
||||
@ -3308,8 +3255,8 @@ func (c *ChannelGraph) ForEachNodeChannelTx(tx kvdb.RTx,
|
||||
// one of the nodes, and wishes to obtain the full LightningNode for the other
|
||||
// end of the channel.
|
||||
func (c *ChannelGraph) FetchOtherNode(tx kvdb.RTx,
|
||||
channel *models.ChannelEdgeInfo, thisNodeKey []byte) (*LightningNode,
|
||||
error) {
|
||||
channel *models.ChannelEdgeInfo, thisNodeKey []byte) (
|
||||
*models.LightningNode, error) {
|
||||
|
||||
// Ensure that the node passed in is actually a member of the channel.
|
||||
var targetNodeBytes [33]byte
|
||||
@ -3322,7 +3269,7 @@ func (c *ChannelGraph) FetchOtherNode(tx kvdb.RTx,
|
||||
return nil, fmt.Errorf("node not participating in this channel")
|
||||
}
|
||||
|
||||
var targetNode *LightningNode
|
||||
var targetNode *models.LightningNode
|
||||
fetchNodeFunc := func(tx kvdb.RTx) error {
|
||||
// First grab the nodes bucket which stores the mapping from
|
||||
// pubKey to node information.
|
||||
@ -3345,7 +3292,9 @@ func (c *ChannelGraph) FetchOtherNode(tx kvdb.RTx,
|
||||
// otherwise we can use the existing db transaction.
|
||||
var err error
|
||||
if tx == nil {
|
||||
err = kvdb.View(c.db, fetchNodeFunc, func() { targetNode = nil })
|
||||
err = kvdb.View(c.db, fetchNodeFunc, func() {
|
||||
targetNode = nil
|
||||
})
|
||||
} else {
|
||||
err = fetchNodeFunc(tx)
|
||||
}
|
||||
@ -3413,7 +3362,7 @@ func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint) (
|
||||
return ErrGraphNoEdgesFound
|
||||
}
|
||||
var b bytes.Buffer
|
||||
if err := writeOutpoint(&b, op); err != nil {
|
||||
if err := WriteOutpoint(&b, op); err != nil {
|
||||
return err
|
||||
}
|
||||
chanID := chanIndex.Get(b.Bytes())
|
||||
@ -3655,37 +3604,41 @@ func (c *ChannelGraph) ChannelView() ([]EdgePoint, error) {
|
||||
// Once we have the proper bucket, we'll range over each key
|
||||
// (which is the channel point for the channel) and decode it,
|
||||
// accumulating each entry.
|
||||
return chanIndex.ForEach(func(chanPointBytes, chanID []byte) error {
|
||||
chanPointReader := bytes.NewReader(chanPointBytes)
|
||||
return chanIndex.ForEach(
|
||||
func(chanPointBytes, chanID []byte) error {
|
||||
chanPointReader := bytes.NewReader(
|
||||
chanPointBytes,
|
||||
)
|
||||
|
||||
var chanPoint wire.OutPoint
|
||||
err := readOutpoint(chanPointReader, &chanPoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var chanPoint wire.OutPoint
|
||||
err := ReadOutpoint(chanPointReader, &chanPoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
edgeInfo, err := fetchChanEdgeInfo(
|
||||
edgeIndex, chanID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
edgeInfo, err := fetchChanEdgeInfo(
|
||||
edgeIndex, chanID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pkScript, err := genMultiSigP2WSH(
|
||||
edgeInfo.BitcoinKey1Bytes[:],
|
||||
edgeInfo.BitcoinKey2Bytes[:],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pkScript, err := genMultiSigP2WSH(
|
||||
edgeInfo.BitcoinKey1Bytes[:],
|
||||
edgeInfo.BitcoinKey2Bytes[:],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
edgePoints = append(edgePoints, EdgePoint{
|
||||
FundingPkScript: pkScript,
|
||||
OutPoint: chanPoint,
|
||||
})
|
||||
edgePoints = append(edgePoints, EdgePoint{
|
||||
FundingPkScript: pkScript,
|
||||
OutPoint: chanPoint,
|
||||
})
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}, func() {
|
||||
edgePoints = nil
|
||||
}); err != nil {
|
||||
@ -3945,7 +3898,7 @@ func (c *ChannelGraph) IsClosedScid(scid lnwire.ShortChannelID) (bool, error) {
|
||||
}
|
||||
|
||||
func putLightningNode(nodeBucket kvdb.RwBucket, aliasBucket kvdb.RwBucket, // nolint:dupl
|
||||
updateIndex kvdb.RwBucket, node *LightningNode) error {
|
||||
updateIndex kvdb.RwBucket, node *models.LightningNode) error {
|
||||
|
||||
var (
|
||||
scratch [16]byte
|
||||
@ -4016,7 +3969,7 @@ func putLightningNode(nodeBucket kvdb.RwBucket, aliasBucket kvdb.RwBucket, // no
|
||||
}
|
||||
|
||||
for _, address := range node.Addresses {
|
||||
if err := serializeAddr(&b, address); err != nil {
|
||||
if err := SerializeAddr(&b, address); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -4074,11 +4027,11 @@ func putLightningNode(nodeBucket kvdb.RwBucket, aliasBucket kvdb.RwBucket, // no
|
||||
}
|
||||
|
||||
func fetchLightningNode(nodeBucket kvdb.RBucket,
|
||||
nodePub []byte) (LightningNode, error) {
|
||||
nodePub []byte) (models.LightningNode, error) {
|
||||
|
||||
nodeBytes := nodeBucket.Get(nodePub)
|
||||
if nodeBytes == nil {
|
||||
return LightningNode{}, ErrGraphNodeNotFound
|
||||
return models.LightningNode{}, ErrGraphNodeNotFound
|
||||
}
|
||||
|
||||
nodeReader := bytes.NewReader(nodeBytes)
|
||||
@ -4141,9 +4094,9 @@ func deserializeLightningNodeCacheable(r io.Reader) (*graphCacheNode, error) {
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func deserializeLightningNode(r io.Reader) (LightningNode, error) {
|
||||
func deserializeLightningNode(r io.Reader) (models.LightningNode, error) {
|
||||
var (
|
||||
node LightningNode
|
||||
node models.LightningNode
|
||||
scratch [8]byte
|
||||
err error
|
||||
)
|
||||
@ -4153,18 +4106,18 @@ func deserializeLightningNode(r io.Reader) (LightningNode, error) {
|
||||
node.Features = lnwire.EmptyFeatureVector()
|
||||
|
||||
if _, err := r.Read(scratch[:]); err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
|
||||
unix := int64(byteOrder.Uint64(scratch[:]))
|
||||
node.LastUpdate = time.Unix(unix, 0)
|
||||
|
||||
if _, err := io.ReadFull(r, node.PubKeyBytes[:]); err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
|
||||
if _, err := r.Read(scratch[:2]); err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
|
||||
hasNodeAnn := byteOrder.Uint16(scratch[:2])
|
||||
@ -4174,8 +4127,8 @@ func deserializeLightningNode(r io.Reader) (LightningNode, error) {
|
||||
node.HaveNodeAnnouncement = false
|
||||
}
|
||||
|
||||
// The rest of the data is optional, and will only be there if we got a node
|
||||
// announcement for this node.
|
||||
// The rest of the data is optional, and will only be there if we got a
|
||||
// node announcement for this node.
|
||||
if !node.HaveNodeAnnouncement {
|
||||
return node, nil
|
||||
}
|
||||
@ -4183,35 +4136,35 @@ func deserializeLightningNode(r io.Reader) (LightningNode, error) {
|
||||
// We did get a node announcement for this node, so we'll have the rest
|
||||
// of the data available.
|
||||
if err := binary.Read(r, byteOrder, &node.Color.R); err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
if err := binary.Read(r, byteOrder, &node.Color.G); err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
if err := binary.Read(r, byteOrder, &node.Color.B); err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
|
||||
node.Alias, err = wire.ReadVarString(r, 0)
|
||||
if err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
|
||||
err = node.Features.Decode(r)
|
||||
if err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
|
||||
if _, err := r.Read(scratch[:2]); err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
numAddresses := int(byteOrder.Uint16(scratch[:2]))
|
||||
|
||||
var addresses []net.Addr
|
||||
for i := 0; i < numAddresses; i++ {
|
||||
address, err := deserializeAddr(r)
|
||||
address, err := DeserializeAddr(r)
|
||||
if err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
addresses = append(addresses, address)
|
||||
}
|
||||
@ -4219,7 +4172,7 @@ func deserializeLightningNode(r io.Reader) (LightningNode, error) {
|
||||
|
||||
node.AuthSigBytes, err = wire.ReadVarBytes(r, 0, 80, "sig")
|
||||
if err != nil {
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
|
||||
// We'll try and see if there are any opaque bytes left, if not, then
|
||||
@ -4231,7 +4184,7 @@ func deserializeLightningNode(r io.Reader) (LightningNode, error) {
|
||||
case err == io.ErrUnexpectedEOF:
|
||||
case err == io.EOF:
|
||||
case err != nil:
|
||||
return LightningNode{}, err
|
||||
return models.LightningNode{}, err
|
||||
}
|
||||
|
||||
return node, nil
|
||||
@ -4281,10 +4234,11 @@ func putChanEdgeInfo(edgeIndex kvdb.RwBucket,
|
||||
return err
|
||||
}
|
||||
|
||||
if err := writeOutpoint(&b, &edgeInfo.ChannelPoint); err != nil {
|
||||
if err := WriteOutpoint(&b, &edgeInfo.ChannelPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(&b, byteOrder, uint64(edgeInfo.Capacity)); err != nil {
|
||||
err := binary.Write(&b, byteOrder, uint64(edgeInfo.Capacity))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := b.Write(chanID[:]); err != nil {
|
||||
@ -4297,7 +4251,7 @@ func putChanEdgeInfo(edgeIndex kvdb.RwBucket,
|
||||
if len(edgeInfo.ExtraOpaqueData) > MaxAllowedExtraOpaqueBytes {
|
||||
return ErrTooManyExtraOpaqueBytes(len(edgeInfo.ExtraOpaqueData))
|
||||
}
|
||||
err := wire.WriteVarBytes(&b, 0, edgeInfo.ExtraOpaqueData)
|
||||
err = wire.WriteVarBytes(&b, 0, edgeInfo.ExtraOpaqueData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -4365,7 +4319,7 @@ func deserializeChanEdgeInfo(r io.Reader) (models.ChannelEdgeInfo, error) {
|
||||
}
|
||||
|
||||
edgeInfo.ChannelPoint = wire.OutPoint{}
|
||||
if err := readOutpoint(r, &edgeInfo.ChannelPoint); err != nil {
|
||||
if err := ReadOutpoint(r, &edgeInfo.ChannelPoint); err != nil {
|
||||
return models.ChannelEdgeInfo{}, err
|
||||
}
|
||||
if err := binary.Read(r, byteOrder, &edgeInfo.Capacity); err != nil {
|
||||
@ -4610,10 +4564,14 @@ func serializeChanEdgePolicy(w io.Writer, edge *models.ChannelEdgePolicy,
|
||||
if err := binary.Write(w, byteOrder, uint64(edge.MinHTLC)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(w, byteOrder, uint64(edge.FeeBaseMSat)); err != nil {
|
||||
err = binary.Write(w, byteOrder, uint64(edge.FeeBaseMSat))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(w, byteOrder, uint64(edge.FeeProportionalMillionths)); err != nil {
|
||||
err = binary.Write(
|
||||
w, byteOrder, uint64(edge.FeeProportionalMillionths),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -4745,3 +4703,34 @@ func deserializeChanEdgePolicyRaw(r io.Reader) (*models.ChannelEdgePolicy,
|
||||
|
||||
return edge, nil
|
||||
}
|
||||
|
||||
// MakeTestGraph creates a new instance of the ChannelGraph for testing
|
||||
// purposes.
|
||||
func MakeTestGraph(t testing.TB, modifiers ...OptionModifier) (*ChannelGraph,
|
||||
error) {
|
||||
|
||||
opts := DefaultOptions()
|
||||
for _, modifier := range modifiers {
|
||||
modifier(opts)
|
||||
}
|
||||
|
||||
// Next, create channelgraph for the first time.
|
||||
backend, backendCleanup, err := kvdb.GetTestBackend(t.TempDir(), "cgr")
|
||||
if err != nil {
|
||||
backendCleanup()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
graph, err := NewChannelGraph(backend)
|
||||
if err != nil {
|
||||
backendCleanup()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = backend.Close()
|
||||
backendCleanup()
|
||||
})
|
||||
|
||||
return graph, nil
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
package channeldb
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
@ -1,10 +1,10 @@
|
||||
package channeldb
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
@ -1,4 +1,4 @@
|
||||
package channeldb
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -21,8 +21,7 @@ import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
@ -37,13 +36,15 @@ var (
|
||||
"[2001:db8:85a3:0:0:8a2e:370:7334]:80")
|
||||
testAddrs = []net.Addr{testAddr, anotherAddr}
|
||||
|
||||
testRBytes, _ = hex.DecodeString("8ce2bc69281ce27da07e6683571319d18e949ddfa2965fb6caa1bf0314f882d7")
|
||||
testSBytes, _ = hex.DecodeString("299105481d63e0f4bc2a88121167221b6700d72a0ead154c03be696a292d24ae")
|
||||
testRScalar = new(btcec.ModNScalar)
|
||||
testSScalar = new(btcec.ModNScalar)
|
||||
_ = testRScalar.SetByteSlice(testRBytes)
|
||||
_ = testSScalar.SetByteSlice(testSBytes)
|
||||
testSig = ecdsa.NewSignature(testRScalar, testSScalar)
|
||||
testRBytes, _ = hex.DecodeString("8ce2bc69281ce27da07e6683571319d18" +
|
||||
"e949ddfa2965fb6caa1bf0314f882d7")
|
||||
testSBytes, _ = hex.DecodeString("299105481d63e0f4bc2a88121167221b6" +
|
||||
"700d72a0ead154c03be696a292d24ae")
|
||||
testRScalar = new(btcec.ModNScalar)
|
||||
testSScalar = new(btcec.ModNScalar)
|
||||
_ = testRScalar.SetByteSlice(testRBytes)
|
||||
_ = testSScalar.SetByteSlice(testSBytes)
|
||||
testSig = ecdsa.NewSignature(testRScalar, testSScalar)
|
||||
|
||||
testFeatures = lnwire.NewFeatureVector(
|
||||
lnwire.NewRawFeatureVector(lnwire.GossipQueriesRequired),
|
||||
@ -51,45 +52,27 @@ var (
|
||||
)
|
||||
|
||||
testPub = route.Vertex{2, 202, 4}
|
||||
|
||||
key = [chainhash.HashSize]byte{
|
||||
0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
|
||||
0x68, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
|
||||
0xd, 0xe7, 0x93, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
|
||||
0x1e, 0xb, 0x4c, 0xf9, 0x9e, 0xc5, 0x8c, 0xe9,
|
||||
}
|
||||
rev = [chainhash.HashSize]byte{
|
||||
0x51, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
|
||||
0x48, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
|
||||
0x2d, 0xe7, 0x93, 0xe4,
|
||||
}
|
||||
)
|
||||
|
||||
// MakeTestGraph creates a new instance of the ChannelGraph for testing purposes.
|
||||
func MakeTestGraph(t testing.TB, modifiers ...OptionModifier) (*ChannelGraph, error) {
|
||||
opts := DefaultOptions()
|
||||
for _, modifier := range modifiers {
|
||||
modifier(&opts)
|
||||
}
|
||||
func createLightningNode(_ kvdb.Backend, priv *btcec.PrivateKey) (
|
||||
*models.LightningNode, error) {
|
||||
|
||||
// Next, create channelgraph for the first time.
|
||||
backend, backendCleanup, err := kvdb.GetTestBackend(t.TempDir(), "cgr")
|
||||
if err != nil {
|
||||
backendCleanup()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
graph, err := NewChannelGraph(
|
||||
backend, opts.RejectCacheSize, opts.ChannelCacheSize,
|
||||
opts.BatchCommitInterval, opts.PreAllocCacheNumNodes,
|
||||
true, false,
|
||||
)
|
||||
if err != nil {
|
||||
backendCleanup()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = backend.Close()
|
||||
backendCleanup()
|
||||
})
|
||||
|
||||
return graph, nil
|
||||
}
|
||||
|
||||
func createLightningNode(db kvdb.Backend, priv *btcec.PrivateKey) (*LightningNode, error) {
|
||||
updateTime := prand.Int63()
|
||||
|
||||
pub := priv.PubKey().SerializeCompressed()
|
||||
n := &LightningNode{
|
||||
n := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
AuthSigBytes: testSig.Serialize(),
|
||||
LastUpdate: time.Unix(updateTime, 0),
|
||||
@ -103,7 +86,7 @@ func createLightningNode(db kvdb.Backend, priv *btcec.PrivateKey) (*LightningNod
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func createTestVertex(db kvdb.Backend) (*LightningNode, error) {
|
||||
func createTestVertex(db kvdb.Backend) (*models.LightningNode, error) {
|
||||
priv, err := btcec.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -120,7 +103,7 @@ func TestNodeInsertionAndDeletion(t *testing.T) {
|
||||
|
||||
// We'd like to test basic insertion/deletion for vertexes from the
|
||||
// graph, so we'll create a test vertex to start with.
|
||||
node := &LightningNode{
|
||||
node := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
AuthSigBytes: testSig.Serialize(),
|
||||
LastUpdate: time.Unix(1232342, 0),
|
||||
@ -144,7 +127,8 @@ func TestNodeInsertionAndDeletion(t *testing.T) {
|
||||
dbNode, err := graph.FetchLightningNode(testPub)
|
||||
require.NoError(t, err, "unable to locate node")
|
||||
|
||||
if _, exists, err := graph.HasLightningNode(dbNode.PubKeyBytes); err != nil {
|
||||
_, exists, err := graph.HasLightningNode(dbNode.PubKeyBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to query for node: %v", err)
|
||||
} else if !exists {
|
||||
t.Fatalf("node should be found but wasn't")
|
||||
@ -180,7 +164,7 @@ func TestPartialNode(t *testing.T) {
|
||||
|
||||
// We want to be able to insert nodes into the graph that only has the
|
||||
// PubKey set.
|
||||
node := &LightningNode{
|
||||
node := &models.LightningNode{
|
||||
HaveNodeAnnouncement: false,
|
||||
PubKeyBytes: testPub,
|
||||
}
|
||||
@ -195,7 +179,8 @@ func TestPartialNode(t *testing.T) {
|
||||
dbNode, err := graph.FetchLightningNode(testPub)
|
||||
require.NoError(t, err, "unable to locate node")
|
||||
|
||||
if _, exists, err := graph.HasLightningNode(dbNode.PubKeyBytes); err != nil {
|
||||
_, exists, err := graph.HasLightningNode(dbNode.PubKeyBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to query for node: %v", err)
|
||||
} else if !exists {
|
||||
t.Fatalf("node should be found but wasn't")
|
||||
@ -203,7 +188,7 @@ func TestPartialNode(t *testing.T) {
|
||||
|
||||
// The two nodes should match exactly! (with default values for
|
||||
// LastUpdate and db set to satisfy compareNodes())
|
||||
node = &LightningNode{
|
||||
node = &models.LightningNode{
|
||||
HaveNodeAnnouncement: false,
|
||||
LastUpdate: time.Unix(0, 0),
|
||||
PubKeyBytes: testPub,
|
||||
@ -366,7 +351,8 @@ func TestEdgeInsertionDeletion(t *testing.T) {
|
||||
|
||||
// Ensure that any query attempts to lookup the delete channel edge are
|
||||
// properly deleted.
|
||||
if _, _, _, err := graph.FetchChannelEdgesByOutpoint(&outpoint); err == nil {
|
||||
_, _, _, err = graph.FetchChannelEdgesByOutpoint(&outpoint)
|
||||
if err == nil {
|
||||
t.Fatalf("channel edge not deleted")
|
||||
}
|
||||
if _, _, _, err := graph.FetchChannelEdgesByID(chanID); err == nil {
|
||||
@ -386,7 +372,7 @@ func TestEdgeInsertionDeletion(t *testing.T) {
|
||||
}
|
||||
|
||||
func createEdge(height, txIndex uint32, txPosition uint16, outPointIndex uint32,
|
||||
node1, node2 *LightningNode) (models.ChannelEdgeInfo,
|
||||
node1, node2 *models.LightningNode) (models.ChannelEdgeInfo,
|
||||
lnwire.ShortChannelID) {
|
||||
|
||||
shortChanID := lnwire.ShortChannelID{
|
||||
@ -548,12 +534,8 @@ func TestDisconnectBlockAtHeight(t *testing.T) {
|
||||
// at height 155.
|
||||
hash, h, err := graph.PruneTip()
|
||||
require.NoError(t, err, "unable to get prune tip")
|
||||
if !blockHash.IsEqual(hash) {
|
||||
t.Fatalf("expected best block to be %x, was %x", blockHash, hash)
|
||||
}
|
||||
if h != height-1 {
|
||||
t.Fatalf("expected best block height to be %d, was %d", height-1, h)
|
||||
}
|
||||
require.True(t, blockHash.IsEqual(hash))
|
||||
require.Equal(t, h, height-1)
|
||||
}
|
||||
|
||||
func assertEdgeInfoEqual(t *testing.T, e1 *models.ChannelEdgeInfo,
|
||||
@ -587,20 +569,19 @@ func assertEdgeInfoEqual(t *testing.T, e1 *models.ChannelEdgeInfo,
|
||||
e2.Features)
|
||||
}
|
||||
|
||||
if !bytes.Equal(e1.AuthProof.NodeSig1Bytes, e2.AuthProof.NodeSig1Bytes) {
|
||||
t.Fatalf("nodesig1 doesn't match: %v vs %v",
|
||||
spew.Sdump(e1.AuthProof.NodeSig1Bytes),
|
||||
spew.Sdump(e2.AuthProof.NodeSig1Bytes))
|
||||
}
|
||||
if !bytes.Equal(e1.AuthProof.NodeSig2Bytes, e2.AuthProof.NodeSig2Bytes) {
|
||||
t.Fatalf("nodesig2 doesn't match")
|
||||
}
|
||||
if !bytes.Equal(e1.AuthProof.BitcoinSig1Bytes, e2.AuthProof.BitcoinSig1Bytes) {
|
||||
t.Fatalf("bitcoinsig1 doesn't match")
|
||||
}
|
||||
if !bytes.Equal(e1.AuthProof.BitcoinSig2Bytes, e2.AuthProof.BitcoinSig2Bytes) {
|
||||
t.Fatalf("bitcoinsig2 doesn't match")
|
||||
}
|
||||
require.True(t, bytes.Equal(
|
||||
e1.AuthProof.NodeSig1Bytes, e2.AuthProof.NodeSig1Bytes,
|
||||
))
|
||||
require.True(t, bytes.Equal(
|
||||
e1.AuthProof.NodeSig2Bytes, e2.AuthProof.NodeSig2Bytes,
|
||||
))
|
||||
require.True(t, bytes.Equal(
|
||||
e1.AuthProof.BitcoinSig1Bytes,
|
||||
e2.AuthProof.BitcoinSig1Bytes,
|
||||
))
|
||||
require.True(t, bytes.Equal(
|
||||
e1.AuthProof.BitcoinSig2Bytes, e2.AuthProof.BitcoinSig2Bytes,
|
||||
))
|
||||
|
||||
if e1.ChannelPoint != e2.ChannelPoint {
|
||||
t.Fatalf("channel point match: %v vs %v", e1.ChannelPoint,
|
||||
@ -618,7 +599,7 @@ func assertEdgeInfoEqual(t *testing.T, e1 *models.ChannelEdgeInfo,
|
||||
}
|
||||
}
|
||||
|
||||
func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) (
|
||||
func createChannelEdge(db kvdb.Backend, node1, node2 *models.LightningNode) (
|
||||
*models.ChannelEdgeInfo, *models.ChannelEdgePolicy,
|
||||
*models.ChannelEdgePolicy) {
|
||||
|
||||
@ -779,7 +760,9 @@ func TestEdgeInfoUpdates(t *testing.T) {
|
||||
|
||||
// Next, attempt to query the channel edges according to the outpoint
|
||||
// of the channel.
|
||||
dbEdgeInfo, dbEdge1, dbEdge2, err = graph.FetchChannelEdgesByOutpoint(&outpoint)
|
||||
dbEdgeInfo, dbEdge1, dbEdge2, err = graph.FetchChannelEdgesByOutpoint(
|
||||
&outpoint,
|
||||
)
|
||||
require.NoError(t, err, "unable to fetch channel by ID")
|
||||
if err := compareEdgePolicies(dbEdge1, edge1); err != nil {
|
||||
t.Fatalf("edge doesn't match: %v", err)
|
||||
@ -790,7 +773,7 @@ func TestEdgeInfoUpdates(t *testing.T) {
|
||||
assertEdgeInfoEqual(t, dbEdgeInfo, edgeInfo)
|
||||
}
|
||||
|
||||
func assertNodeInCache(t *testing.T, g *ChannelGraph, n *LightningNode,
|
||||
func assertNodeInCache(t *testing.T, g *ChannelGraph, n *models.LightningNode,
|
||||
expectedFeatures *lnwire.FeatureVector) {
|
||||
|
||||
// Let's check the internal view first.
|
||||
@ -1109,11 +1092,13 @@ func TestGraphTraversalCacheable(t *testing.T) {
|
||||
// Create a map of all nodes with the iteration we know works (because
|
||||
// it is tested in another test).
|
||||
nodeMap := make(map[route.Vertex]struct{})
|
||||
err = graph.ForEachNode(func(tx kvdb.RTx, n *LightningNode) error {
|
||||
nodeMap[n.PubKeyBytes] = struct{}{}
|
||||
err = graph.ForEachNode(
|
||||
func(tx kvdb.RTx, n *models.LightningNode) error {
|
||||
nodeMap[n.PubKeyBytes] = struct{}{}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, nodeMap, numNodes)
|
||||
|
||||
@ -1182,8 +1167,8 @@ func TestGraphCacheTraversal(t *testing.T) {
|
||||
delete(chanIndex, d.ChannelID)
|
||||
|
||||
if !d.OutPolicySet || d.InPolicy == nil {
|
||||
return fmt.Errorf("channel policy not " +
|
||||
"present")
|
||||
return fmt.Errorf("channel policy " +
|
||||
"not present")
|
||||
}
|
||||
|
||||
// The incoming edge should also indicate that
|
||||
@ -1212,9 +1197,9 @@ func TestGraphCacheTraversal(t *testing.T) {
|
||||
}
|
||||
|
||||
func fillTestGraph(t require.TestingT, graph *ChannelGraph, numNodes,
|
||||
numChannels int) (map[uint64]struct{}, []*LightningNode) {
|
||||
numChannels int) (map[uint64]struct{}, []*models.LightningNode) {
|
||||
|
||||
nodes := make([]*LightningNode, numNodes)
|
||||
nodes := make([]*models.LightningNode, numNodes)
|
||||
nodeIndex := map[string]struct{}{}
|
||||
for i := 0; i < numNodes; i++ {
|
||||
node, err := createTestVertex(graph.db)
|
||||
@ -1232,10 +1217,12 @@ func fillTestGraph(t require.TestingT, graph *ChannelGraph, numNodes,
|
||||
|
||||
// Iterate over each node as returned by the graph, if all nodes are
|
||||
// reached, then the map created above should be empty.
|
||||
err := graph.ForEachNode(func(_ kvdb.RTx, node *LightningNode) error {
|
||||
delete(nodeIndex, node.Alias)
|
||||
return nil
|
||||
})
|
||||
err := graph.ForEachNode(
|
||||
func(_ kvdb.RTx, node *models.LightningNode) error {
|
||||
delete(nodeIndex, node.Alias)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, nodeIndex, 0)
|
||||
|
||||
@ -1245,7 +1232,9 @@ func fillTestGraph(t require.TestingT, graph *ChannelGraph, numNodes,
|
||||
for n := 0; n < numNodes-1; n++ {
|
||||
node1 := nodes[n]
|
||||
node2 := nodes[n+1]
|
||||
if bytes.Compare(node1.PubKeyBytes[:], node2.PubKeyBytes[:]) == -1 {
|
||||
if bytes.Compare(
|
||||
node1.PubKeyBytes[:], node2.PubKeyBytes[:],
|
||||
) == -1 {
|
||||
node1, node2 = node2, node1
|
||||
}
|
||||
|
||||
@ -1299,8 +1288,8 @@ func fillTestGraph(t require.TestingT, graph *ChannelGraph, numNodes,
|
||||
return chanIndex, nodes
|
||||
}
|
||||
|
||||
func assertPruneTip(t *testing.T, graph *ChannelGraph, blockHash *chainhash.Hash,
|
||||
blockHeight uint32) {
|
||||
func assertPruneTip(t *testing.T, graph *ChannelGraph,
|
||||
blockHash *chainhash.Hash, blockHeight uint32) {
|
||||
|
||||
pruneHash, pruneHeight, err := graph.PruneTip()
|
||||
if err != nil {
|
||||
@ -1340,10 +1329,12 @@ func assertNumChans(t *testing.T, graph *ChannelGraph, n int) {
|
||||
|
||||
func assertNumNodes(t *testing.T, graph *ChannelGraph, n int) {
|
||||
numNodes := 0
|
||||
err := graph.ForEachNode(func(_ kvdb.RTx, _ *LightningNode) error {
|
||||
numNodes++
|
||||
return nil
|
||||
})
|
||||
err := graph.ForEachNode(
|
||||
func(_ kvdb.RTx, _ *models.LightningNode) error {
|
||||
numNodes++
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
_, _, line, _ := runtime.Caller(1)
|
||||
t.Fatalf("line %v: unable to scan nodes: %v", line, err)
|
||||
@ -1351,7 +1342,8 @@ func assertNumNodes(t *testing.T, graph *ChannelGraph, n int) {
|
||||
|
||||
if numNodes != n {
|
||||
_, _, line, _ := runtime.Caller(1)
|
||||
t.Fatalf("line %v: expected %v nodes, got %v", line, n, numNodes)
|
||||
t.Fatalf("line %v: expected %v nodes, got %v", line, n,
|
||||
numNodes)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1375,7 +1367,9 @@ func assertChanViewEqual(t *testing.T, a []EdgePoint, b []EdgePoint) {
|
||||
}
|
||||
}
|
||||
|
||||
func assertChanViewEqualChanPoints(t *testing.T, a []EdgePoint, b []*wire.OutPoint) {
|
||||
func assertChanViewEqualChanPoints(t *testing.T, a []EdgePoint,
|
||||
b []*wire.OutPoint) {
|
||||
|
||||
if len(a) != len(b) {
|
||||
_, _, line, _ := runtime.Caller(1)
|
||||
t.Fatalf("line %v: chan views don't match", line)
|
||||
@ -1411,7 +1405,7 @@ func TestGraphPruning(t *testing.T) {
|
||||
// and enough edges to create a fully connected graph. The graph will
|
||||
// be rather simple, representing a straight line.
|
||||
const numNodes = 5
|
||||
graphNodes := make([]*LightningNode, numNodes)
|
||||
graphNodes := make([]*models.LightningNode, numNodes)
|
||||
for i := 0; i < numNodes; i++ {
|
||||
node, err := createTestVertex(graph.db)
|
||||
if err != nil {
|
||||
@ -1454,13 +1448,17 @@ func TestGraphPruning(t *testing.T) {
|
||||
copy(edgeInfo.NodeKey1Bytes[:], graphNodes[i].PubKeyBytes[:])
|
||||
copy(edgeInfo.NodeKey2Bytes[:], graphNodes[i+1].PubKeyBytes[:])
|
||||
copy(edgeInfo.BitcoinKey1Bytes[:], graphNodes[i].PubKeyBytes[:])
|
||||
copy(edgeInfo.BitcoinKey2Bytes[:], graphNodes[i+1].PubKeyBytes[:])
|
||||
copy(
|
||||
edgeInfo.BitcoinKey2Bytes[:],
|
||||
graphNodes[i+1].PubKeyBytes[:],
|
||||
)
|
||||
if err := graph.AddChannelEdge(&edgeInfo); err != nil {
|
||||
t.Fatalf("unable to add node: %v", err)
|
||||
}
|
||||
|
||||
pkScript, err := genMultiSigP2WSH(
|
||||
edgeInfo.BitcoinKey1Bytes[:], edgeInfo.BitcoinKey2Bytes[:],
|
||||
edgeInfo.BitcoinKey1Bytes[:],
|
||||
edgeInfo.BitcoinKey2Bytes[:],
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to gen multi-sig p2wsh: %v", err)
|
||||
@ -1792,7 +1790,9 @@ func TestChanUpdatesInHorizon(t *testing.T) {
|
||||
|
||||
assertEdgeInfoEqual(t, chanExp.Info, chanRet.Info)
|
||||
|
||||
err := compareEdgePolicies(chanExp.Policy1, chanRet.Policy1)
|
||||
err := compareEdgePolicies(
|
||||
chanExp.Policy1, chanRet.Policy1,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1829,7 +1829,7 @@ func TestNodeUpdatesInHorizon(t *testing.T) {
|
||||
// We'll create 10 node announcements, each with an update timestamp 10
|
||||
// seconds after the other.
|
||||
const numNodes = 10
|
||||
nodeAnns := make([]LightningNode, 0, numNodes)
|
||||
nodeAnns := make([]models.LightningNode, 0, numNodes)
|
||||
for i := 0; i < numNodes; i++ {
|
||||
nodeAnn, err := createTestVertex(graph.db)
|
||||
if err != nil {
|
||||
@ -1855,7 +1855,7 @@ func TestNodeUpdatesInHorizon(t *testing.T) {
|
||||
start time.Time
|
||||
end time.Time
|
||||
|
||||
resp []LightningNode
|
||||
resp []models.LightningNode
|
||||
}{
|
||||
// If we query for a time range that's strictly below our set
|
||||
// of updates, then we'll get an empty result back.
|
||||
@ -1899,7 +1899,9 @@ func TestNodeUpdatesInHorizon(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, queryCase := range queryCases {
|
||||
resp, err := graph.NodeUpdatesInHorizon(queryCase.start, queryCase.end)
|
||||
resp, err := graph.NodeUpdatesInHorizon(
|
||||
queryCase.start, queryCase.end,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to query for nodes: %v", err)
|
||||
}
|
||||
@ -2428,7 +2430,7 @@ func TestFilterChannelRange(t *testing.T) {
|
||||
)
|
||||
|
||||
updateTimeSeed := time.Now().Unix()
|
||||
maybeAddPolicy := func(chanID uint64, node *LightningNode,
|
||||
maybeAddPolicy := func(chanID uint64, node *models.LightningNode,
|
||||
node2 bool) time.Time {
|
||||
|
||||
var chanFlags lnwire.ChanUpdateChanFlags
|
||||
@ -2745,7 +2747,9 @@ func TestIncompleteChannelPolicies(t *testing.T) {
|
||||
}
|
||||
|
||||
// Ensure that channel is reported with unknown policies.
|
||||
checkPolicies := func(node *LightningNode, expectedIn, expectedOut bool) {
|
||||
checkPolicies := func(node *models.LightningNode, expectedIn,
|
||||
expectedOut bool) {
|
||||
|
||||
calls := 0
|
||||
err := graph.ForEachNodeChannel(node.PubKeyBytes,
|
||||
func(_ kvdb.RTx, _ *models.ChannelEdgeInfo, outEdge,
|
||||
@ -3066,9 +3070,7 @@ func TestAddChannelEdgeShellNodes(t *testing.T) {
|
||||
|
||||
node2, err = graph.FetchLightningNode(node2.PubKeyBytes)
|
||||
require.NoError(t, err, "unable to fetch node2")
|
||||
if node2.HaveNodeAnnouncement {
|
||||
t.Fatalf("should have shell announcement for node2, but is full")
|
||||
}
|
||||
require.False(t, node2.HaveNodeAnnouncement)
|
||||
}
|
||||
|
||||
// TestNodePruningUpdateIndexDeletion tests that once a node has been removed
|
||||
@ -3165,7 +3167,7 @@ func TestNodeIsPublic(t *testing.T) {
|
||||
|
||||
// After creating all of our nodes and edges, we'll add them to each
|
||||
// participant's graph.
|
||||
nodes := []*LightningNode{aliceNode, bobNode, carolNode}
|
||||
nodes := []*models.LightningNode{aliceNode, bobNode, carolNode}
|
||||
edges := []*models.ChannelEdgeInfo{&aliceBobEdge, &bobCarolEdge}
|
||||
graphs := []*ChannelGraph{aliceGraph, bobGraph, carolGraph}
|
||||
for _, graph := range graphs {
|
||||
@ -3183,17 +3185,19 @@ func TestNodeIsPublic(t *testing.T) {
|
||||
|
||||
// checkNodes is a helper closure that will be used to assert that the
|
||||
// given nodes are seen as public/private within the given graphs.
|
||||
checkNodes := func(nodes []*LightningNode, graphs []*ChannelGraph,
|
||||
public bool) {
|
||||
checkNodes := func(nodes []*models.LightningNode,
|
||||
graphs []*ChannelGraph, public bool) {
|
||||
|
||||
t.Helper()
|
||||
|
||||
for _, node := range nodes {
|
||||
for _, graph := range graphs {
|
||||
isPublic, err := graph.IsPublicNode(node.PubKeyBytes)
|
||||
isPublic, err := graph.IsPublicNode(
|
||||
node.PubKeyBytes,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to determine if pivot "+
|
||||
"is public: %v", err)
|
||||
t.Fatalf("unable to determine if "+
|
||||
"pivot is public: %v", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
@ -3224,7 +3228,7 @@ func TestNodeIsPublic(t *testing.T) {
|
||||
}
|
||||
}
|
||||
checkNodes(
|
||||
[]*LightningNode{aliceNode},
|
||||
[]*models.LightningNode{aliceNode},
|
||||
[]*ChannelGraph{bobGraph, carolGraph},
|
||||
false,
|
||||
)
|
||||
@ -3255,7 +3259,7 @@ func TestNodeIsPublic(t *testing.T) {
|
||||
// With the modifications above, Bob should now be seen as a private
|
||||
// node from both Alice's and Carol's perspective.
|
||||
checkNodes(
|
||||
[]*LightningNode{bobNode},
|
||||
[]*models.LightningNode{bobNode},
|
||||
[]*ChannelGraph{aliceGraph, carolGraph},
|
||||
false,
|
||||
)
|
||||
@ -3298,8 +3302,8 @@ func TestDisabledChannelIDs(t *testing.T) {
|
||||
disabledChanIds, err := graph.DisabledChannelIDs()
|
||||
require.NoError(t, err, "unable to get disabled channel ids")
|
||||
if len(disabledChanIds) > 0 {
|
||||
t.Fatalf("expected empty disabled channels, got %v disabled channels",
|
||||
len(disabledChanIds))
|
||||
t.Fatalf("expected empty disabled channels, got %v disabled "+
|
||||
"channels", len(disabledChanIds))
|
||||
}
|
||||
|
||||
// Add one disabled policy and ensure the channel is still not in the
|
||||
@ -3311,8 +3315,8 @@ func TestDisabledChannelIDs(t *testing.T) {
|
||||
disabledChanIds, err = graph.DisabledChannelIDs()
|
||||
require.NoError(t, err, "unable to get disabled channel ids")
|
||||
if len(disabledChanIds) > 0 {
|
||||
t.Fatalf("expected empty disabled channels, got %v disabled channels",
|
||||
len(disabledChanIds))
|
||||
t.Fatalf("expected empty disabled channels, got %v disabled "+
|
||||
"channels", len(disabledChanIds))
|
||||
}
|
||||
|
||||
// Add second disabled policy and ensure the channel is now in the
|
||||
@ -3323,12 +3327,15 @@ func TestDisabledChannelIDs(t *testing.T) {
|
||||
}
|
||||
disabledChanIds, err = graph.DisabledChannelIDs()
|
||||
require.NoError(t, err, "unable to get disabled channel ids")
|
||||
if len(disabledChanIds) != 1 || disabledChanIds[0] != edgeInfo.ChannelID {
|
||||
if len(disabledChanIds) != 1 ||
|
||||
disabledChanIds[0] != edgeInfo.ChannelID {
|
||||
|
||||
t.Fatalf("expected disabled channel with id %v, "+
|
||||
"got %v", edgeInfo.ChannelID, disabledChanIds)
|
||||
}
|
||||
|
||||
// Delete the channel edge and ensure it is removed from the disabled list.
|
||||
// Delete the channel edge and ensure it is removed from the disabled
|
||||
// list.
|
||||
if err = graph.DeleteChannelEdges(
|
||||
false, true, edgeInfo.ChannelID,
|
||||
); err != nil {
|
||||
@ -3337,8 +3344,8 @@ func TestDisabledChannelIDs(t *testing.T) {
|
||||
disabledChanIds, err = graph.DisabledChannelIDs()
|
||||
require.NoError(t, err, "unable to get disabled channel ids")
|
||||
if len(disabledChanIds) > 0 {
|
||||
t.Fatalf("expected empty disabled channels, got %v disabled channels",
|
||||
len(disabledChanIds))
|
||||
t.Fatalf("expected empty disabled channels, got %v disabled "+
|
||||
"channels", len(disabledChanIds))
|
||||
}
|
||||
}
|
||||
|
||||
@ -3441,7 +3448,9 @@ func TestEdgePolicyMissingMaxHtcl(t *testing.T) {
|
||||
copy(indexKey[:], scratch[:])
|
||||
byteOrder.PutUint64(indexKey[8:], edge1.ChannelID)
|
||||
|
||||
updateIndex, err := edges.CreateBucketIfNotExists(edgeUpdateIndexBucket)
|
||||
updateIndex, err := edges.CreateBucketIfNotExists(
|
||||
edgeUpdateIndexBucket,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -3574,10 +3583,10 @@ func TestGraphZombieIndex(t *testing.T) {
|
||||
// compareNodes is used to compare two LightningNodes while excluding the
|
||||
// Features struct, which cannot be compared as the semantics for reserializing
|
||||
// the featuresMap have not been defined.
|
||||
func compareNodes(a, b *LightningNode) error {
|
||||
func compareNodes(a, b *models.LightningNode) error {
|
||||
if a.LastUpdate != b.LastUpdate {
|
||||
return fmt.Errorf("node LastUpdate doesn't match: expected %v, \n"+
|
||||
"got %v", a.LastUpdate, b.LastUpdate)
|
||||
return fmt.Errorf("node LastUpdate doesn't match: expected "+
|
||||
"%v, got %v", a.LastUpdate, b.LastUpdate)
|
||||
}
|
||||
if !reflect.DeepEqual(a.Addresses, b.Addresses) {
|
||||
return fmt.Errorf("Addresses doesn't match: expected %#v, \n "+
|
||||
@ -3596,8 +3605,9 @@ func compareNodes(a, b *LightningNode) error {
|
||||
"got %#v", a.Alias, b.Alias)
|
||||
}
|
||||
if !reflect.DeepEqual(a.HaveNodeAnnouncement, b.HaveNodeAnnouncement) {
|
||||
return fmt.Errorf("HaveNodeAnnouncement doesn't match: expected %#v, \n "+
|
||||
"got %#v", a.HaveNodeAnnouncement, b.HaveNodeAnnouncement)
|
||||
return fmt.Errorf("HaveNodeAnnouncement doesn't match: "+
|
||||
"expected %#v, got %#v", a.HaveNodeAnnouncement,
|
||||
b.HaveNodeAnnouncement)
|
||||
}
|
||||
if !bytes.Equal(a.ExtraOpaqueData, b.ExtraOpaqueData) {
|
||||
return fmt.Errorf("extra data doesn't match: %v vs %v",
|
||||
@ -3615,8 +3625,8 @@ func compareEdgePolicies(a, b *models.ChannelEdgePolicy) error {
|
||||
"got %v", a.ChannelID, b.ChannelID)
|
||||
}
|
||||
if !reflect.DeepEqual(a.LastUpdate, b.LastUpdate) {
|
||||
return fmt.Errorf("edge LastUpdate doesn't match: expected %#v, \n "+
|
||||
"got %#v", a.LastUpdate, b.LastUpdate)
|
||||
return fmt.Errorf("edge LastUpdate doesn't match: "+
|
||||
"expected %#v, got %#v", a.LastUpdate, b.LastUpdate)
|
||||
}
|
||||
if a.MessageFlags != b.MessageFlags {
|
||||
return fmt.Errorf("MessageFlags doesn't match: expected %v, "+
|
||||
@ -4004,12 +4014,7 @@ func TestGraphLoading(t *testing.T) {
|
||||
defer backend.Close()
|
||||
defer backendCleanup()
|
||||
|
||||
opts := DefaultOptions()
|
||||
graph, err := NewChannelGraph(
|
||||
backend, opts.RejectCacheSize, opts.ChannelCacheSize,
|
||||
opts.BatchCommitInterval, opts.PreAllocCacheNumNodes,
|
||||
true, false,
|
||||
)
|
||||
graph, err := NewChannelGraph(backend)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Populate the graph with test data.
|
||||
@ -4019,11 +4024,7 @@ func TestGraphLoading(t *testing.T) {
|
||||
|
||||
// Recreate the graph. This should cause the graph cache to be
|
||||
// populated.
|
||||
graphReloaded, err := NewChannelGraph(
|
||||
backend, opts.RejectCacheSize, opts.ChannelCacheSize,
|
||||
opts.BatchCommitInterval, opts.PreAllocCacheNumNodes,
|
||||
true, false,
|
||||
)
|
||||
graphReloaded, err := NewChannelGraph(backend)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Assert that the cache content is identical.
|
31
graph/db/log.go
Normal file
31
graph/db/log.go
Normal file
@ -0,0 +1,31 @@
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
"github.com/lightningnetwork/lnd/build"
|
||||
)
|
||||
|
||||
// Subsystem defines the logging code for this subsystem.
|
||||
const Subsystem = "GRDB"
|
||||
|
||||
// log is a logger that is initialized with no output filters. This
|
||||
// means the package will not perform any logging by default until the caller
|
||||
// requests it.
|
||||
var log btclog.Logger
|
||||
|
||||
func init() {
|
||||
UseLogger(build.NewSubLogger(Subsystem, nil))
|
||||
}
|
||||
|
||||
// DisableLog disables all library log output. Logging output is disabled
|
||||
// by default until UseLogger is called.
|
||||
func DisableLog() {
|
||||
UseLogger(btclog.Disabled)
|
||||
}
|
||||
|
||||
// UseLogger uses a specified Logger to output package logging info.
|
||||
// This should be used in preference to SetLogWriter if the caller is also
|
||||
// using btclog.
|
||||
func UseLogger(logger btclog.Logger) {
|
||||
log = logger
|
||||
}
|
133
graph/db/models/node.go
Normal file
133
graph/db/models/node.go
Normal file
@ -0,0 +1,133 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
// LightningNode represents an individual vertex/node within the channel graph.
|
||||
// A node is connected to other nodes by one or more channel edges emanating
|
||||
// from it. As the graph is directed, a node will also have an incoming edge
|
||||
// attached to it for each outgoing edge.
|
||||
type LightningNode struct {
|
||||
// PubKeyBytes is the raw bytes of the public key of the target node.
|
||||
PubKeyBytes [33]byte
|
||||
pubKey *btcec.PublicKey
|
||||
|
||||
// HaveNodeAnnouncement indicates whether we received a node
|
||||
// announcement for this particular node. If true, the remaining fields
|
||||
// will be set, if false only the PubKey is known for this node.
|
||||
HaveNodeAnnouncement bool
|
||||
|
||||
// LastUpdate is the last time the vertex information for this node has
|
||||
// been updated.
|
||||
LastUpdate time.Time
|
||||
|
||||
// Address is the TCP address this node is reachable over.
|
||||
Addresses []net.Addr
|
||||
|
||||
// Color is the selected color for the node.
|
||||
Color color.RGBA
|
||||
|
||||
// Alias is a nick-name for the node. The alias can be used to confirm
|
||||
// a node's identity or to serve as a short ID for an address book.
|
||||
Alias string
|
||||
|
||||
// AuthSigBytes is the raw signature under the advertised public key
|
||||
// which serves to authenticate the attributes announced by this node.
|
||||
AuthSigBytes []byte
|
||||
|
||||
// Features is the list of protocol features supported by this node.
|
||||
Features *lnwire.FeatureVector
|
||||
|
||||
// ExtraOpaqueData is the set of data that was appended to this
|
||||
// message, some of which we may not actually know how to iterate or
|
||||
// parse. By holding onto this data, we ensure that we're able to
|
||||
// properly validate the set of signatures that cover these new fields,
|
||||
// and ensure we're able to make upgrades to the network in a forwards
|
||||
// compatible manner.
|
||||
ExtraOpaqueData []byte
|
||||
|
||||
// TODO(roasbeef): discovery will need storage to keep it's last IP
|
||||
// address and re-announce if interface changes?
|
||||
|
||||
// TODO(roasbeef): add update method and fetch?
|
||||
}
|
||||
|
||||
// PubKey is the node's long-term identity public key. This key will be used to
|
||||
// authenticated any advertisements/updates sent by the node.
|
||||
//
|
||||
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||
// to fully deserialize the pubkey if absolutely necessary.
|
||||
func (l *LightningNode) PubKey() (*btcec.PublicKey, error) {
|
||||
if l.pubKey != nil {
|
||||
return l.pubKey, nil
|
||||
}
|
||||
|
||||
key, err := btcec.ParsePubKey(l.PubKeyBytes[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l.pubKey = key
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// AuthSig is a signature under the advertised public key which serves to
|
||||
// authenticate the attributes announced by this node.
|
||||
//
|
||||
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||
// to fully deserialize the signature if absolutely necessary.
|
||||
func (l *LightningNode) AuthSig() (*ecdsa.Signature, error) {
|
||||
return ecdsa.ParseSignature(l.AuthSigBytes)
|
||||
}
|
||||
|
||||
// AddPubKey is a setter-link method that can be used to swap out the public
|
||||
// key for a node.
|
||||
func (l *LightningNode) AddPubKey(key *btcec.PublicKey) {
|
||||
l.pubKey = key
|
||||
copy(l.PubKeyBytes[:], key.SerializeCompressed())
|
||||
}
|
||||
|
||||
// NodeAnnouncement retrieves the latest node announcement of the node.
|
||||
func (l *LightningNode) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement,
|
||||
error) {
|
||||
|
||||
if !l.HaveNodeAnnouncement {
|
||||
return nil, fmt.Errorf("node does not have node announcement")
|
||||
}
|
||||
|
||||
alias, err := lnwire.NewNodeAlias(l.Alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeAnn := &lnwire.NodeAnnouncement{
|
||||
Features: l.Features.RawFeatureVector,
|
||||
NodeID: l.PubKeyBytes,
|
||||
RGBColor: l.Color,
|
||||
Alias: alias,
|
||||
Addresses: l.Addresses,
|
||||
Timestamp: uint32(l.LastUpdate.Unix()),
|
||||
ExtraOpaqueData: l.ExtraOpaqueData,
|
||||
}
|
||||
|
||||
if !signed {
|
||||
return nodeAnn, nil
|
||||
}
|
||||
|
||||
sig, err := lnwire.NewSigFromECDSARawSignature(l.AuthSigBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeAnn.Signature = sig
|
||||
|
||||
return nodeAnn, nil
|
||||
}
|
100
graph/db/options.go
Normal file
100
graph/db/options.go
Normal file
@ -0,0 +1,100 @@
|
||||
package graphdb
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
// DefaultRejectCacheSize is the default number of rejectCacheEntries to
|
||||
// cache for use in the rejection cache of incoming gossip traffic. This
|
||||
// produces a cache size of around 1MB.
|
||||
DefaultRejectCacheSize = 50000
|
||||
|
||||
// DefaultChannelCacheSize is the default number of ChannelEdges cached
|
||||
// in order to reply to gossip queries. This produces a cache size of
|
||||
// around 40MB.
|
||||
DefaultChannelCacheSize = 20000
|
||||
|
||||
// DefaultPreAllocCacheNumNodes is the default number of channels we
|
||||
// assume for mainnet for pre-allocating the graph cache. As of
|
||||
// September 2021, there currently are 14k nodes in a strictly pruned
|
||||
// graph, so we choose a number that is slightly higher.
|
||||
DefaultPreAllocCacheNumNodes = 15000
|
||||
)
|
||||
|
||||
// Options holds parameters for tuning and customizing a graph.DB.
|
||||
type Options struct {
|
||||
// RejectCacheSize is the maximum number of rejectCacheEntries to hold
|
||||
// in the rejection cache.
|
||||
RejectCacheSize int
|
||||
|
||||
// ChannelCacheSize is the maximum number of ChannelEdges to hold in the
|
||||
// channel cache.
|
||||
ChannelCacheSize int
|
||||
|
||||
// BatchCommitInterval is the maximum duration the batch schedulers will
|
||||
// wait before attempting to commit a pending set of updates.
|
||||
BatchCommitInterval time.Duration
|
||||
|
||||
// PreAllocCacheNumNodes is the number of nodes we expect to be in the
|
||||
// graph cache, so we can pre-allocate the map accordingly.
|
||||
PreAllocCacheNumNodes int
|
||||
|
||||
// UseGraphCache denotes whether the in-memory graph cache should be
|
||||
// used or a fallback version that uses the underlying database for
|
||||
// path finding.
|
||||
UseGraphCache bool
|
||||
|
||||
// NoMigration specifies that underlying backend was opened in read-only
|
||||
// mode and migrations shouldn't be performed. This can be useful for
|
||||
// applications that use the channeldb package as a library.
|
||||
NoMigration bool
|
||||
}
|
||||
|
||||
// DefaultOptions returns an Options populated with default values.
|
||||
func DefaultOptions() *Options {
|
||||
return &Options{
|
||||
RejectCacheSize: DefaultRejectCacheSize,
|
||||
ChannelCacheSize: DefaultChannelCacheSize,
|
||||
PreAllocCacheNumNodes: DefaultPreAllocCacheNumNodes,
|
||||
UseGraphCache: true,
|
||||
NoMigration: false,
|
||||
}
|
||||
}
|
||||
|
||||
// OptionModifier is a function signature for modifying the default Options.
|
||||
type OptionModifier func(*Options)
|
||||
|
||||
// WithRejectCacheSize sets the RejectCacheSize to n.
|
||||
func WithRejectCacheSize(n int) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.RejectCacheSize = n
|
||||
}
|
||||
}
|
||||
|
||||
// WithChannelCacheSize sets the ChannelCacheSize to n.
|
||||
func WithChannelCacheSize(n int) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.ChannelCacheSize = n
|
||||
}
|
||||
}
|
||||
|
||||
// WithPreAllocCacheNumNodes sets the PreAllocCacheNumNodes to n.
|
||||
func WithPreAllocCacheNumNodes(n int) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.PreAllocCacheNumNodes = n
|
||||
}
|
||||
}
|
||||
|
||||
// WithBatchCommitInterval sets the batch commit interval for the interval batch
|
||||
// schedulers.
|
||||
func WithBatchCommitInterval(interval time.Duration) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.BatchCommitInterval = interval
|
||||
}
|
||||
}
|
||||
|
||||
// WithUseGraphCache sets the UseGraphCache option to the given value.
|
||||
func WithUseGraphCache(use bool) OptionModifier {
|
||||
return func(o *Options) {
|
||||
o.UseGraphCache = use
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package channeldb
|
||||
package graphdb
|
||||
|
||||
// rejectFlags is a compact representation of various metadata stored by the
|
||||
// reject cache about a particular channel.
|
@ -1,4 +1,4 @@
|
||||
package channeldb
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"reflect"
|
11
graph/db/setup_test.go
Normal file
11
graph/db/setup_test.go
Normal file
@ -0,0 +1,11 @@
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
kvdb.RunTests(m)
|
||||
}
|
@ -3,7 +3,7 @@ package graphsession
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
@ -84,7 +84,7 @@ func (g *session) close() error {
|
||||
//
|
||||
// NOTE: Part of the routing.Graph interface.
|
||||
func (g *session) ForEachNodeChannel(nodePub route.Vertex,
|
||||
cb func(channel *channeldb.DirectedChannel) error) error {
|
||||
cb func(channel *graphdb.DirectedChannel) error) error {
|
||||
|
||||
return g.graph.ForEachNodeDirectedChannel(g.tx, nodePub, cb)
|
||||
}
|
||||
@ -129,7 +129,7 @@ type graph interface {
|
||||
// NOTE: if a nil tx is provided, then it is expected that the
|
||||
// implementation create a read only tx.
|
||||
ForEachNodeDirectedChannel(tx kvdb.RTx, node route.Vertex,
|
||||
cb func(channel *channeldb.DirectedChannel) error) error
|
||||
cb func(channel *graphdb.DirectedChannel) error) error
|
||||
|
||||
// FetchNodeFeatures returns the features of a given node. If no
|
||||
// features are known for the node, an empty feature vector is returned.
|
||||
@ -138,4 +138,4 @@ type graph interface {
|
||||
|
||||
// A compile-time check to ensure that *channeldb.ChannelGraph implements the
|
||||
// graph interface.
|
||||
var _ graph = (*channeldb.ChannelGraph)(nil)
|
||||
var _ graph = (*graphdb.ChannelGraph)(nil)
|
@ -6,8 +6,8 @@ import (
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/batch"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
@ -23,7 +23,7 @@ type ChannelGraphSource interface {
|
||||
// AddNode is used to add information about a node to the router
|
||||
// database. If the node with this pubkey is not present in an existing
|
||||
// channel, it will be ignored.
|
||||
AddNode(node *channeldb.LightningNode,
|
||||
AddNode(node *models.LightningNode,
|
||||
op ...batch.SchedulerOption) error
|
||||
|
||||
// AddEdge is used to add edge/channel to the topology of the router,
|
||||
@ -69,8 +69,7 @@ type ChannelGraphSource interface {
|
||||
// ForAllOutgoingChannels is used to iterate over all channels
|
||||
// emanating from the "source" node which is the center of the
|
||||
// star-graph.
|
||||
ForAllOutgoingChannels(cb func(tx kvdb.RTx,
|
||||
c *models.ChannelEdgeInfo,
|
||||
ForAllOutgoingChannels(cb func(c *models.ChannelEdgeInfo,
|
||||
e *models.ChannelEdgePolicy) error) error
|
||||
|
||||
// CurrentBlockHeight returns the block height from POV of the router
|
||||
@ -85,10 +84,10 @@ type ChannelGraphSource interface {
|
||||
// FetchLightningNode attempts to look up a target node by its identity
|
||||
// public key. channeldb.ErrGraphNodeNotFound is returned if the node
|
||||
// doesn't exist within the graph.
|
||||
FetchLightningNode(route.Vertex) (*channeldb.LightningNode, error)
|
||||
FetchLightningNode(route.Vertex) (*models.LightningNode, error)
|
||||
|
||||
// ForEachNode is used to iterate over every node in the known graph.
|
||||
ForEachNode(func(node *channeldb.LightningNode) error) error
|
||||
ForEachNode(func(node *models.LightningNode) error) error
|
||||
}
|
||||
|
||||
// DB is an interface describing a persisted Lightning Network graph.
|
||||
@ -116,7 +115,7 @@ type DB interface {
|
||||
// channel within the known channel graph. The set of UTXO's (along with
|
||||
// their scripts) returned are the ones that need to be watched on
|
||||
// chain to detect channel closes on the resident blockchain.
|
||||
ChannelView() ([]channeldb.EdgePoint, error)
|
||||
ChannelView() ([]graphdb.EdgePoint, error)
|
||||
|
||||
// PruneGraphNodes is a garbage collection method which attempts to
|
||||
// prune out any nodes from the channel graph that are currently
|
||||
@ -129,7 +128,7 @@ type DB interface {
|
||||
// treated as the center node within a star-graph. This method may be
|
||||
// used to kick off a path finding algorithm in order to explore the
|
||||
// reachability of another node based off the source node.
|
||||
SourceNode() (*channeldb.LightningNode, error)
|
||||
SourceNode() (*models.LightningNode, error)
|
||||
|
||||
// DisabledChannelIDs returns the channel ids of disabled channels.
|
||||
// A channel is disabled when two of the associated ChanelEdgePolicies
|
||||
@ -142,13 +141,13 @@ type DB interface {
|
||||
// edges that exist at the time of the query. This can be used to
|
||||
// respond to peer queries that are seeking to fill in gaps in their
|
||||
// view of the channel graph.
|
||||
FetchChanInfos(chanIDs []uint64) ([]channeldb.ChannelEdge, error)
|
||||
FetchChanInfos(chanIDs []uint64) ([]graphdb.ChannelEdge, error)
|
||||
|
||||
// ChanUpdatesInHorizon returns all the known channel edges which have
|
||||
// at least one edge that has an update timestamp within the specified
|
||||
// horizon.
|
||||
ChanUpdatesInHorizon(startTime, endTime time.Time) (
|
||||
[]channeldb.ChannelEdge, error)
|
||||
[]graphdb.ChannelEdge, error)
|
||||
|
||||
// DeleteChannelEdges removes edges with the given channel IDs from the
|
||||
// database and marks them as zombies. This ensures that we're unable to
|
||||
@ -200,7 +199,7 @@ type DB interface {
|
||||
// update that node's information. Note that this method is expected to
|
||||
// only be called to update an already present node from a node
|
||||
// announcement, or to insert a node found in a channel update.
|
||||
AddLightningNode(node *channeldb.LightningNode,
|
||||
AddLightningNode(node *models.LightningNode,
|
||||
op ...batch.SchedulerOption) error
|
||||
|
||||
// AddChannelEdge adds a new (undirected, blank) edge to the graph
|
||||
@ -239,14 +238,14 @@ type DB interface {
|
||||
// FetchLightningNode attempts to look up a target node by its identity
|
||||
// public key. If the node isn't found in the database, then
|
||||
// ErrGraphNodeNotFound is returned.
|
||||
FetchLightningNode(nodePub route.Vertex) (*channeldb.LightningNode,
|
||||
FetchLightningNode(nodePub route.Vertex) (*models.LightningNode,
|
||||
error)
|
||||
|
||||
// ForEachNode iterates through all the stored vertices/nodes in the
|
||||
// graph, executing the passed callback with each node encountered. If
|
||||
// the callback returns an error, then the transaction is aborted and
|
||||
// the iteration stops early.
|
||||
ForEachNode(cb func(kvdb.RTx, *channeldb.LightningNode) error) error
|
||||
ForEachNode(cb func(kvdb.RTx, *models.LightningNode) error) error
|
||||
|
||||
// ForEachNodeChannel iterates through all channels of the given node,
|
||||
// executing the passed callback with an edge info structure and the
|
||||
|
@ -10,8 +10,7 @@ import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
@ -318,7 +317,7 @@ func addToTopologyChange(graph DB, update *TopologyChange,
|
||||
|
||||
// Any node announcement maps directly to a NetworkNodeUpdate struct.
|
||||
// No further data munging or db queries are required.
|
||||
case *channeldb.LightningNode:
|
||||
case *models.LightningNode:
|
||||
pubKey, err := m.PubKey()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -17,8 +17,8 @@ import (
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
graphdb "github.com/lightningnetwork/lnd/graph/db"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
@ -77,14 +77,14 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func createTestNode(t *testing.T) *channeldb.LightningNode {
|
||||
func createTestNode(t *testing.T) *models.LightningNode {
|
||||
updateTime := prand.Int63()
|
||||
|
||||
priv, err := btcec.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
pub := priv.PubKey().SerializeCompressed()
|
||||
n := &channeldb.LightningNode{
|
||||
n := &models.LightningNode{
|
||||
HaveNodeAnnouncement: true,
|
||||
LastUpdate: time.Unix(updateTime, 0),
|
||||
Addresses: testAddrs,
|
||||
@ -99,7 +99,7 @@ func createTestNode(t *testing.T) *channeldb.LightningNode {
|
||||
}
|
||||
|
||||
func randEdgePolicy(chanID *lnwire.ShortChannelID,
|
||||
node *channeldb.LightningNode) (*models.ChannelEdgePolicy, error) {
|
||||
node *models.LightningNode) (*models.ChannelEdgePolicy, error) {
|
||||
|
||||
InboundFee := models.InboundFee{
|
||||
Base: prand.Int31() * -1,
|
||||
@ -315,7 +315,7 @@ func (m *mockChainView) Reset() {
|
||||
m.staleBlocks = make(chan *chainview.FilteredBlock, 10)
|
||||
}
|
||||
|
||||
func (m *mockChainView) UpdateFilter(ops []channeldb.EdgePoint, updateHeight uint32) error {
|
||||
func (m *mockChainView) UpdateFilter(ops []graphdb.EdgePoint, _ uint32) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
@ -686,7 +686,7 @@ func TestNodeUpdateNotification(t *testing.T) {
|
||||
t.Fatalf("unable to add node: %v", err)
|
||||
}
|
||||
|
||||
assertNodeNtfnCorrect := func(t *testing.T, ann *channeldb.LightningNode,
|
||||
assertNodeNtfnCorrect := func(t *testing.T, ann *models.LightningNode,
|
||||
nodeUpdate *NetworkNodeUpdate) {
|
||||
|
||||
nodeKey, _ := ann.PubKey()
|
||||
@ -1019,7 +1019,7 @@ func TestEncodeHexColor(t *testing.T) {
|
||||
type testCtx struct {
|
||||
builder *Builder
|
||||
|
||||
graph *channeldb.ChannelGraph
|
||||
graph *graphdb.ChannelGraph
|
||||
|
||||
aliases map[string]route.Vertex
|
||||
|
||||
@ -1088,7 +1088,7 @@ func (c *testCtx) RestartBuilder(t *testing.T) {
|
||||
|
||||
// makeTestGraph creates a new instance of a channeldb.ChannelGraph for testing
|
||||
// purposes.
|
||||
func makeTestGraph(t *testing.T, useCache bool) (*channeldb.ChannelGraph,
|
||||
func makeTestGraph(t *testing.T, useCache bool) (*graphdb.ChannelGraph,
|
||||
kvdb.Backend, error) {
|
||||
|
||||
// Create channelgraph for the first time.
|
||||
@ -1099,11 +1099,8 @@ func makeTestGraph(t *testing.T, useCache bool) (*channeldb.ChannelGraph,
|
||||
|
||||
t.Cleanup(backendCleanup)
|
||||
|
||||
opts := channeldb.DefaultOptions()
|
||||
graph, err := channeldb.NewChannelGraph(
|
||||
backend, opts.RejectCacheSize, opts.ChannelCacheSize,
|
||||
opts.BatchCommitInterval, opts.PreAllocCacheNumNodes,
|
||||
useCache, false,
|
||||
graph, err := graphdb.NewChannelGraph(
|
||||
backend, graphdb.WithUseGraphCache(useCache),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -1113,7 +1110,7 @@ func makeTestGraph(t *testing.T, useCache bool) (*channeldb.ChannelGraph,
|
||||
}
|
||||
|
||||
type testGraphInstance struct {
|
||||
graph *channeldb.ChannelGraph
|
||||
graph *graphdb.ChannelGraph
|
||||
graphBackend kvdb.Backend
|
||||
|
||||
// aliasMap is a map from a node's alias to its public key. This type is
|
||||
|
@ -4,8 +4,7 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
)
|
||||
@ -151,7 +150,7 @@ func (v *ValidationBarrier) InitJobDependencies(job interface{}) {
|
||||
case *lnwire.NodeAnnouncement:
|
||||
// TODO(roasbeef): node ann needs to wait on existing channel updates
|
||||
return
|
||||
case *channeldb.LightningNode:
|
||||
case *models.LightningNode:
|
||||
return
|
||||
case *lnwire.AnnounceSignatures1:
|
||||
// TODO(roasbeef): need to wait on chan ann?
|
||||
@ -195,7 +194,7 @@ func (v *ValidationBarrier) WaitForDependants(job interface{}) error {
|
||||
jobDesc = fmt.Sprintf("job=lnwire.ChannelEdgePolicy, scid=%v",
|
||||
msg.ChannelID)
|
||||
|
||||
case *channeldb.LightningNode:
|
||||
case *models.LightningNode:
|
||||
vertex := route.Vertex(msg.PubKeyBytes)
|
||||
signals, ok = v.nodeAnnDependencies[vertex]
|
||||
|
||||
@ -291,7 +290,7 @@ func (v *ValidationBarrier) SignalDependants(job interface{}, allow bool) {
|
||||
// For all other job types, we'll delete the tracking entries from the
|
||||
// map, as if we reach this point, then all dependants have already
|
||||
// finished executing and we can proceed.
|
||||
case *channeldb.LightningNode:
|
||||
case *models.LightningNode:
|
||||
delete(v.nodeAnnDependencies, route.Vertex(msg.PubKeyBytes))
|
||||
case *lnwire.NodeAnnouncement:
|
||||
delete(v.nodeAnnDependencies, route.Vertex(msg.NodeID))
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
@ -625,9 +625,7 @@ func makeCircuitDB(t *testing.T, path string) *channeldb.DB {
|
||||
path = t.TempDir()
|
||||
}
|
||||
|
||||
db, err := channeldb.Open(path)
|
||||
require.NoError(t, err, "unable to open channel db")
|
||||
t.Cleanup(func() { db.Close() })
|
||||
db := channeldb.OpenForTesting(t, path)
|
||||
|
||||
return db
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
)
|
||||
|
||||
// heldHtlcSet keeps track of outstanding intercepted forwards. It exposes
|
||||
|
@ -3,7 +3,7 @@ package htlcswitch
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnutils"
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
|
@ -15,9 +15,9 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btclog/v2"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/contractcourt"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
|
@ -25,9 +25,9 @@ import (
|
||||
sphinx "github.com/lightningnetwork/lightning-onion"
|
||||
"github.com/lightningnetwork/lnd/build"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/contractcourt"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
@ -2169,7 +2169,7 @@ func newSingleLinkTestHarness(t *testing.T, chanAmt,
|
||||
BaseFee: lnwire.NewMSatFromSatoshis(1),
|
||||
TimeLockDelta: 6,
|
||||
}
|
||||
invoiceRegistry = newMockRegistry(globalPolicy.TimeLockDelta)
|
||||
invoiceRegistry = newMockRegistry(t)
|
||||
)
|
||||
|
||||
pCache := newMockPreimageCache()
|
||||
@ -2267,7 +2267,6 @@ func newSingleLinkTestHarness(t *testing.T, chanAmt,
|
||||
|
||||
t.Cleanup(func() {
|
||||
close(alicePeer.quit)
|
||||
invoiceRegistry.cleanup()
|
||||
})
|
||||
|
||||
harness := singleLinkTestHarness{
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@ -23,10 +22,10 @@ import (
|
||||
sphinx "github.com/lightningnetwork/lightning-onion"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"github.com/lightningnetwork/lnd/contractcourt"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lnpeer"
|
||||
@ -216,11 +215,7 @@ func initSwitchWithTempDB(t testing.TB, startingHeight uint32) (*Switch,
|
||||
error) {
|
||||
|
||||
tempPath := filepath.Join(t.TempDir(), "switchdb")
|
||||
db, err := channeldb.Open(tempPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.Cleanup(func() { db.Close() })
|
||||
db := channeldb.OpenForTesting(t, tempPath)
|
||||
|
||||
s, err := initSwitchWithDB(startingHeight, db)
|
||||
if err != nil {
|
||||
@ -254,9 +249,7 @@ func newMockServer(t testing.TB, name string, startingHeight uint32,
|
||||
|
||||
t.Cleanup(func() { _ = htlcSwitch.Stop() })
|
||||
|
||||
registry := newMockRegistry(defaultDelta)
|
||||
|
||||
t.Cleanup(func() { registry.cleanup() })
|
||||
registry := newMockRegistry(t)
|
||||
|
||||
return &mockServer{
|
||||
t: t,
|
||||
@ -977,37 +970,12 @@ func (f *mockChannelLink) CommitmentCustomBlob() fn.Option[tlv.Blob] {
|
||||
|
||||
var _ ChannelLink = (*mockChannelLink)(nil)
|
||||
|
||||
func newDB() (*channeldb.DB, func(), error) {
|
||||
// First, create a temporary directory to be used for the duration of
|
||||
// this test.
|
||||
tempDirName, err := os.MkdirTemp("", "channeldb")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Next, create channeldb for the first time.
|
||||
cdb, err := channeldb.Open(tempDirName)
|
||||
if err != nil {
|
||||
os.RemoveAll(tempDirName)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
cleanUp := func() {
|
||||
cdb.Close()
|
||||
os.RemoveAll(tempDirName)
|
||||
}
|
||||
|
||||
return cdb, cleanUp, nil
|
||||
}
|
||||
|
||||
const testInvoiceCltvExpiry = 6
|
||||
|
||||
type mockInvoiceRegistry struct {
|
||||
settleChan chan lntypes.Hash
|
||||
|
||||
registry *invoices.InvoiceRegistry
|
||||
|
||||
cleanup func()
|
||||
}
|
||||
|
||||
type mockChainNotifier struct {
|
||||
@ -1024,11 +992,8 @@ func (m *mockChainNotifier) RegisterBlockEpochNtfn(*chainntnfs.BlockEpoch) (
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newMockRegistry(minDelta uint32) *mockInvoiceRegistry {
|
||||
cdb, cleanup, err := newDB()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
func newMockRegistry(t testing.TB) *mockInvoiceRegistry {
|
||||
cdb := channeldb.OpenForTesting(t, t.TempDir())
|
||||
|
||||
modifierMock := &invoices.MockHtlcModifier{}
|
||||
registry := invoices.NewRegistry(
|
||||
@ -1046,7 +1011,6 @@ func newMockRegistry(minDelta uint32) *mockInvoiceRegistry {
|
||||
|
||||
return &mockInvoiceRegistry{
|
||||
registry: registry,
|
||||
cleanup: cleanup,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ package htlcswitch
|
||||
|
||||
import (
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/record"
|
||||
|
@ -101,11 +101,7 @@ func TestNetworkResultStore(t *testing.T) {
|
||||
|
||||
const numResults = 4
|
||||
|
||||
db, err := channeldb.Open(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { db.Close() })
|
||||
db := channeldb.OpenForTesting(t, t.TempDir())
|
||||
|
||||
store := newNetworkResultStore(db)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user