channeldb: add FetchAllChannels method to return all active channels
This commit introduces a new method to channeldb: ‘FetchAllChannels’. This method can be used to obtain the state of all active (currently open) channels within the database. This method can be used for compute basic channel-based metrics or exposed as an RPC in order to allow clients to display/query channel data.
This commit is contained in:
parent
3354685292
commit
9191fbd317
120
channeldb/db.go
120
channeldb/db.go
@ -162,40 +162,104 @@ func (d *DB) FetchOpenChannels(nodeID *btcec.PublicKey) ([]*OpenChannel, error)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once we have the node's channel bucket, iterate through each
|
// Finally, we both of the necessary buckets retrieved, fetch
|
||||||
// item in the inner chan ID bucket. This bucket acts as an
|
// all the active channels related to this node.
|
||||||
// index for all channels we currently have open with this node.
|
nodeChannels, err := d.fetchNodeChannels(openChanBucket,
|
||||||
nodeChanIDBucket := nodeChanBucket.Bucket(chanIDBucket[:])
|
nodeChanBucket)
|
||||||
if nodeChanIDBucket == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := nodeChanIDBucket.ForEach(func(k, v []byte) error {
|
|
||||||
if k == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
outBytes := bytes.NewReader(k)
|
|
||||||
chanID := &wire.OutPoint{}
|
|
||||||
if err := readOutpoint(outBytes, chanID); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
oChannel, err := fetchOpenChannel(openChanBucket,
|
|
||||||
nodeChanBucket, chanID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
oChannel.Db = d
|
|
||||||
|
|
||||||
channels = append(channels, oChannel)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channels = nodeChannels
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
return channels, err
|
return channels, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fetchNodeChannels retrieves all active channels from the target
|
||||||
|
// nodeChanBucket. This function is typically used to fetch all the active
|
||||||
|
// channels related to a particualr node.
|
||||||
|
func (d *DB) fetchNodeChannels(openChanBucket,
|
||||||
|
nodeChanBucket *bolt.Bucket) ([]*OpenChannel, error) {
|
||||||
|
|
||||||
|
var channels []*OpenChannel
|
||||||
|
|
||||||
|
// Once we have the node's channel bucket, iterate through each
|
||||||
|
// item in the inner chan ID bucket. This bucket acts as an
|
||||||
|
// index for all channels we currently have open with this node.
|
||||||
|
nodeChanIDBucket := nodeChanBucket.Bucket(chanIDBucket[:])
|
||||||
|
if nodeChanIDBucket == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
err := nodeChanIDBucket.ForEach(func(k, v []byte) error {
|
||||||
|
if k == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
outBytes := bytes.NewReader(k)
|
||||||
|
chanID := &wire.OutPoint{}
|
||||||
|
if err := readOutpoint(outBytes, chanID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
oChannel, err := fetchOpenChannel(openChanBucket,
|
||||||
|
nodeChanBucket, chanID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
oChannel.Db = d
|
||||||
|
|
||||||
|
channels = append(channels, oChannel)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return channels, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchAllChannels attempts to retrieve all open channels currently stored
|
||||||
|
// within the database. If no active channels exist within the network, then
|
||||||
|
// ErrNoActiveChannels is returned.
|
||||||
|
func (d *DB) FetchAllChannels() ([]*OpenChannel, error) {
|
||||||
|
var channels []*OpenChannel
|
||||||
|
|
||||||
|
err := d.store.View(func(tx *bolt.Tx) error {
|
||||||
|
// Get the bucket dedicated to storing the meta-data for open
|
||||||
|
// channels.
|
||||||
|
openChanBucket := tx.Bucket(openChannelBucket)
|
||||||
|
if openChanBucket == nil {
|
||||||
|
return ErrNoActiveChannels
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, fetch the bucket dedicated to storing meta-data
|
||||||
|
// related to all nodes. All keys within this bucket are the
|
||||||
|
// serialized public keys of all our direct counterparties.
|
||||||
|
nodeMetaBucket := tx.Bucket(nodeInfoBucket)
|
||||||
|
if nodeMetaBucket == nil {
|
||||||
|
return fmt.Errorf("node bucket not created")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally for each node public key in the bucket, fetch all
|
||||||
|
// the channels related to this particualr ndoe.
|
||||||
|
return nodeMetaBucket.ForEach(func(k, v []byte) error {
|
||||||
|
nodeChanBucket := openChanBucket.Bucket(k)
|
||||||
|
if nodeChanBucket == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeChannels, err := d.fetchNodeChannels(openChanBucket,
|
||||||
|
nodeChanBucket)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
channels = append(channels, nodeChannels...)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return channels, err
|
||||||
|
}
|
||||||
|
@ -49,6 +49,7 @@ type LinkNode struct {
|
|||||||
// channel should be unilaterally closed due to inactivity.
|
// channel should be unilaterally closed due to inactivity.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef): replace with block hash/height?
|
// TODO(roasbeef): replace with block hash/height?
|
||||||
|
// * possibly add a time-value metric into the heuristic?
|
||||||
LastSeen time.Time
|
LastSeen time.Time
|
||||||
|
|
||||||
// Addresses is a list of IP address in which either we were able to
|
// Addresses is a list of IP address in which either we were able to
|
||||||
|
Loading…
Reference in New Issue
Block a user