channeldb: split ChannelEdge into two structs, info and policy
This commit splits the prior ChannelEdge struct into two distinct structs: ChannelEdgeInfo and ChannelEdgePolicy. The info structs stores the _full_ information that was used to advertise the channel, while the policy struct contains the information that’s needed in order to use the information for routing purposes. With this split we can eliminate a number of hacks within the rest of the codebase that were added as a result of data unavailability if one or neither edge was present. Finally a bit of field renaming has taken place (Exipiry -> TimeLockDelta), etc.
This commit is contained in:
parent
8387092409
commit
2c29a20a8d
@ -50,7 +50,7 @@ var (
|
|||||||
// directed: nodes may have different policies w.r.t to fees for their
|
// directed: nodes may have different policies w.r.t to fees for their
|
||||||
// respective directions.
|
// respective directions.
|
||||||
//
|
//
|
||||||
// maps: pubKey || edgeID -> edge for node
|
// maps: pubKey || edgeID -> edge policy for node
|
||||||
edgeBucket = []byte("graph-edge")
|
edgeBucket = []byte("graph-edge")
|
||||||
|
|
||||||
// chanStart is an array of all zero bytes which is used to perform
|
// chanStart is an array of all zero bytes which is used to perform
|
||||||
@ -59,13 +59,16 @@ var (
|
|||||||
chanStart [8]byte
|
chanStart [8]byte
|
||||||
|
|
||||||
// edgeIndexBucket is an index which can be used to iterate all edges
|
// edgeIndexBucket is an index which can be used to iterate all edges
|
||||||
// in the bucket, grouping them according to their in/out nodes. This
|
// in the bucket, grouping them according to their in/out nodes.
|
||||||
|
// Additionally, the items in this bucket also contain the complete
|
||||||
|
// edge information for a channel. The edge information includes the
|
||||||
|
// capacity of the channel, the nodes that made the channel, etc. This
|
||||||
// bucket resides within the edgeBucket above. Creation of a edge
|
// bucket resides within the edgeBucket above. Creation of a edge
|
||||||
// proceeds in two phases: first the edge is added to the edge index,
|
// proceeds in two phases: first the edge is added to the edge index,
|
||||||
// afterwards the edgeBucket can be updated with the latest details of
|
// afterwards the edgeBucket can be updated with the latest details of
|
||||||
// the edge as they are announced on the network.
|
// the edge as they are announced on the network.
|
||||||
//
|
//
|
||||||
// maps: chanID -> pub1 || pub2
|
// maps: chanID -> pubKey1 || pubKey2 || restofEdgeInfo
|
||||||
edgeIndexBucket = []byte("edge-index")
|
edgeIndexBucket = []byte("edge-index")
|
||||||
|
|
||||||
// channelPointBucket maps a channel's full outpoint (txid:index) to
|
// channelPointBucket maps a channel's full outpoint (txid:index) to
|
||||||
@ -77,7 +80,7 @@ var (
|
|||||||
channelPointBucket = []byte("chan-index")
|
channelPointBucket = []byte("chan-index")
|
||||||
|
|
||||||
// graphMetaBucket is a top-level bucket which stores various meta-deta
|
// graphMetaBucket is a top-level bucket which stores various meta-deta
|
||||||
// related to the on-disk channel graph. Data strored in this bucket
|
// related to the on-disk channel graph. Data stored in this bucket
|
||||||
// includes the block to which the graph has been synced to, the total
|
// includes the block to which the graph has been synced to, the total
|
||||||
// number of channels, etc.
|
// number of channels, etc.
|
||||||
graphMetaBucket = []byte("graph-meta")
|
graphMetaBucket = []byte("graph-meta")
|
||||||
@ -117,9 +120,10 @@ type ChannelGraph struct {
|
|||||||
// If the callback returns an error, then the transaction is aborted and the
|
// If the callback returns an error, then the transaction is aborted and the
|
||||||
// iteration stops early.
|
// iteration stops early.
|
||||||
//
|
//
|
||||||
// NOTE: If an edge can't be found, ro wasn't advertised, then a nil pointer
|
// NOTE: If an edge can't be found, or wasn't advertised, then a nil pointer
|
||||||
// will be passed into the callback.
|
// for that particular channel edge routing policy will be passed into the
|
||||||
func (c *ChannelGraph) ForEachChannel(cb func(*ChannelEdge, *ChannelEdge) error) error {
|
// callback.
|
||||||
|
func (c *ChannelGraph) ForEachChannel(cb func(*ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy) error) error {
|
||||||
// TODO(roasbeef): ptr map to reduce # of allocs? no duplicates
|
// TODO(roasbeef): ptr map to reduce # of allocs? no duplicates
|
||||||
|
|
||||||
return c.db.View(func(tx *bolt.Tx) error {
|
return c.db.View(func(tx *bolt.Tx) error {
|
||||||
@ -144,12 +148,18 @@ func (c *ChannelGraph) ForEachChannel(cb func(*ChannelEdge, *ChannelEdge) error)
|
|||||||
|
|
||||||
// For each edge pair within the edge index, we fetch each edge
|
// For each edge pair within the edge index, we fetch each edge
|
||||||
// itself and also the node information in order to fully
|
// itself and also the node information in order to fully
|
||||||
// populated the objecvt.
|
// populated the object.
|
||||||
return edgeIndex.ForEach(func(chanID, edgeInfo []byte) error {
|
return edgeIndex.ForEach(func(chanID, edgeInfoBytes []byte) error {
|
||||||
|
infoReader := bytes.NewReader(edgeInfoBytes)
|
||||||
|
edgeInfo, err := deserializeChanEdgeInfo(infoReader)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// The first node is contained within the first half of
|
// The first node is contained within the first half of
|
||||||
// the edge information.
|
// the edge information.
|
||||||
node1Pub := edgeInfo[:33]
|
node1Pub := edgeInfoBytes[:33]
|
||||||
edge1, err := fetchChannelEdge(edges, chanID, node1Pub, nodes)
|
edge1, err := fetchChanEdgePolicy(edges, chanID, node1Pub, nodes)
|
||||||
if err != nil && err != ErrEdgeNotFound &&
|
if err != nil && err != ErrEdgeNotFound &&
|
||||||
err != ErrGraphNodeNotFound {
|
err != ErrGraphNodeNotFound {
|
||||||
return err
|
return err
|
||||||
@ -167,8 +177,8 @@ func (c *ChannelGraph) ForEachChannel(cb func(*ChannelEdge, *ChannelEdge) error)
|
|||||||
|
|
||||||
// Similarly, the second node is contained within the
|
// Similarly, the second node is contained within the
|
||||||
// latter half of the edge information.
|
// latter half of the edge information.
|
||||||
node2Pub := edgeInfo[33:]
|
node2Pub := edgeInfoBytes[33:]
|
||||||
edge2, err := fetchChannelEdge(edges, chanID, node2Pub, nodes)
|
edge2, err := fetchChanEdgePolicy(edges, chanID, node2Pub, nodes)
|
||||||
if err != nil && err != ErrEdgeNotFound &&
|
if err != nil && err != ErrEdgeNotFound &&
|
||||||
err != ErrGraphNodeNotFound {
|
err != ErrGraphNodeNotFound {
|
||||||
return err
|
return err
|
||||||
@ -187,7 +197,7 @@ func (c *ChannelGraph) ForEachChannel(cb func(*ChannelEdge, *ChannelEdge) error)
|
|||||||
// With both edges read, execute the call back. IF this
|
// With both edges read, execute the call back. IF this
|
||||||
// function returns an error then the transaction will
|
// function returns an error then the transaction will
|
||||||
// be aborted.
|
// be aborted.
|
||||||
return cb(edge1, edge2)
|
return cb(edgeInfo, edge1, edge2)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -375,33 +385,15 @@ func (c *ChannelGraph) DeleteLightningNode(nodePub *btcec.PublicKey) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddChannelEdge adds a new (undirected, blank) edge to the graph database. An
|
// AddChannelEdge adds a new (undirected, blank) edge to the graph database. An
|
||||||
// undirected edge from the two target nodes are created. The chanPoint and
|
// undirected edge from the two target nodes are created. The information
|
||||||
// chanID are used to uniquely identify the edge globally within the database.
|
// stored denotes the static attributes of the channel, such as the channelID,
|
||||||
func (c *ChannelGraph) AddChannelEdge(from, to *btcec.PublicKey,
|
// the keys involved in creation of the channel, and the set of features that
|
||||||
chanPoint *wire.OutPoint, chanID uint64) error {
|
// the channel supports. The chanPoint and chanID are used to uniquely identify
|
||||||
|
// the edge globally within the database.
|
||||||
|
func (c *ChannelGraph) AddChannelEdge(edge *ChannelEdgeInfo) error {
|
||||||
// Construct the channel's primary key which is the 8-byte channel ID.
|
// Construct the channel's primary key which is the 8-byte channel ID.
|
||||||
var chanKey [8]byte
|
var chanKey [8]byte
|
||||||
binary.BigEndian.PutUint64(chanKey[:], chanID)
|
binary.BigEndian.PutUint64(chanKey[:], edge.ChannelID)
|
||||||
|
|
||||||
var (
|
|
||||||
node1 []byte
|
|
||||||
node2 []byte
|
|
||||||
)
|
|
||||||
|
|
||||||
fromBytes := from.SerializeCompressed()
|
|
||||||
toBytes := to.SerializeCompressed()
|
|
||||||
|
|
||||||
// On-disk, we order the value for the edge's key with the "smaller"
|
|
||||||
// pubkey coming before the larger one. This ensures that all edges
|
|
||||||
// have a deterministic ordering.
|
|
||||||
if bytes.Compare(fromBytes, toBytes) == -1 {
|
|
||||||
node1 = fromBytes
|
|
||||||
node2 = toBytes
|
|
||||||
} else {
|
|
||||||
node1 = toBytes
|
|
||||||
node2 = fromBytes
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.db.Update(func(tx *bolt.Tx) error {
|
return c.db.Update(func(tx *bolt.Tx) error {
|
||||||
edges, err := tx.CreateBucketIfNotExists(edgeBucket)
|
edges, err := tx.CreateBucketIfNotExists(edgeBucket)
|
||||||
@ -426,18 +418,15 @@ func (c *ChannelGraph) AddChannelEdge(from, to *btcec.PublicKey,
|
|||||||
|
|
||||||
// If the edge hasn't been created yet, then we'll first add it
|
// If the edge hasn't been created yet, then we'll first add it
|
||||||
// to the edge index in order to associate the edge between two
|
// to the edge index in order to associate the edge between two
|
||||||
// nodes.
|
// nodes and also store the static components of the channel.
|
||||||
var edgeInfo [66]byte
|
if err := putChanEdgeInfo(edgeIndex, edge, chanKey); err != nil {
|
||||||
copy(edgeInfo[:33], node1)
|
|
||||||
copy(edgeInfo[33:], node2)
|
|
||||||
if err := edgeIndex.Put(chanKey[:], edgeInfo[:]); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally we add it to the channel index which maps channel
|
// Finally we add it to the channel index which maps channel
|
||||||
// points (outpoints) to the shorter channel ID's.
|
// points (outpoints) to the shorter channel ID's.
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := writeOutpoint(&b, chanPoint); err != nil {
|
if err := writeOutpoint(&b, &edge.ChannelPoint); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return chanIndex.Put(b.Bytes(), chanKey[:])
|
return chanIndex.Put(b.Bytes(), chanKey[:])
|
||||||
@ -484,7 +473,7 @@ func (c *ChannelGraph) HasChannelEdge(chanID uint64) (time.Time, time.Time, bool
|
|||||||
return ErrGraphNodeNotFound
|
return ErrGraphNodeNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
e1, e2, err := fetchEdges(edgeIndex, edges, nodes,
|
e1, e2, err := fetchChanEdgePolicies(edgeIndex, edges, nodes,
|
||||||
channelID[:], c.db)
|
channelID[:], c.db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -736,13 +725,14 @@ func delChannelByEdge(edges *bolt.Bucket, edgeIndex *bolt.Bucket,
|
|||||||
return chanIndex.Delete(b.Bytes())
|
return chanIndex.Delete(b.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateEdgeInfo updates the edge information for a single directed edge
|
// UpdateEdgePolicy updates the edge routing policy for a single directed edge
|
||||||
// within the database for the referenced channel. The `flags` attribute within
|
// within the database for the referenced channel. The `flags` attribute within
|
||||||
// the ChannelEdge determines which of the directed edges are being updated. If
|
// the ChannelEdgePolicy determines which of the directed edges are being
|
||||||
// the flag is 1, then the first node's information is being updated, otherwise
|
// updated. If the flag is 1, then the first node's information is being
|
||||||
// it's the second node's information.
|
// updated, otherwise it's the second node's information. The node ordering is
|
||||||
func (r *ChannelGraph) UpdateEdgeInfo(edge *ChannelEdge) error {
|
// determined tby the lexicographical ordering of the identity public keys of
|
||||||
|
// the nodes on either side of the channel.
|
||||||
|
func (r *ChannelGraph) UpdateEdgePolicy(edge *ChannelEdgePolicy) error {
|
||||||
return r.db.Update(func(tx *bolt.Tx) error {
|
return r.db.Update(func(tx *bolt.Tx) error {
|
||||||
edges, err := tx.CreateBucketIfNotExists(edgeBucket)
|
edges, err := tx.CreateBucketIfNotExists(edgeBucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -765,20 +755,20 @@ func (r *ChannelGraph) UpdateEdgeInfo(edge *ChannelEdge) error {
|
|||||||
return ErrEdgeNotFound
|
return ErrEdgeNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depending on the flags value parsed above, either the first
|
// Depending on the flags value passed above, either the first
|
||||||
// or second node is being updated.
|
// or second edge policy is being updated.
|
||||||
var fromNode, toNode []byte
|
var fromNode, toNode []byte
|
||||||
if edge.Flags == 0 {
|
if edge.Flags == 0 {
|
||||||
fromNode = nodeInfo[:33]
|
fromNode = nodeInfo[:33]
|
||||||
toNode = nodeInfo[33:]
|
toNode = nodeInfo[33:67]
|
||||||
} else {
|
} else {
|
||||||
fromNode = nodeInfo[33:]
|
fromNode = nodeInfo[33:67]
|
||||||
toNode = nodeInfo[:33]
|
toNode = nodeInfo[:33]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, with the direction of the edge being updated
|
// Finally, with the direction of the edge being updated
|
||||||
// identified, we update the on-disk edge representation.
|
// identified, we update the on-disk edge representation.
|
||||||
return putChannelEdge(edges, edge, fromNode, toNode)
|
return putChanEdgePolicy(edges, edge, fromNode, toNode)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,6 +795,12 @@ type LightningNode struct {
|
|||||||
// a node's identity or to serve as a short ID for an address book.
|
// a node's identity or to serve as a short ID for an address book.
|
||||||
Alias string
|
Alias string
|
||||||
|
|
||||||
|
// AuthSig is a signature under the advertised public key which serves
|
||||||
|
// to authenticate the attributes announced by this node.
|
||||||
|
//
|
||||||
|
// TODO(roasbeef): hook into serialization once full verification is in
|
||||||
|
AuthSig *btcec.Signature
|
||||||
|
|
||||||
db *DB
|
db *DB
|
||||||
|
|
||||||
// TODO(roasbeef): discovery will need storage to keep it's last IP
|
// TODO(roasbeef): discovery will need storage to keep it's last IP
|
||||||
@ -814,7 +810,7 @@ type LightningNode struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FetchLightningNode attempts to look up a target node by its identity public
|
// FetchLightningNode attempts to look up a target node by its identity public
|
||||||
// key. If the node iwn't found in the database, then ErrGraphNodeNotFound is
|
// key. If the node isn't found in the database, then ErrGraphNodeNotFound is
|
||||||
// returned.
|
// returned.
|
||||||
func (c *ChannelGraph) FetchLightningNode(pub *btcec.PublicKey) (*LightningNode, error) {
|
func (c *ChannelGraph) FetchLightningNode(pub *btcec.PublicKey) (*LightningNode, error) {
|
||||||
var node *LightningNode
|
var node *LightningNode
|
||||||
@ -910,6 +906,7 @@ func (c *ChannelGraph) HasLightningNode(pub *btcec.PublicKey) (time.Time, bool,
|
|||||||
// Otherwise the first argument should be nil and a fresh transaction will be
|
// Otherwise the first argument should be nil and a fresh transaction will be
|
||||||
// created to execute the graph traversal.
|
// created to execute the graph traversal.
|
||||||
func (l *LightningNode) ForEachChannel(tx *bolt.Tx, cb func(*ChannelEdge) error) error {
|
func (l *LightningNode) ForEachChannel(tx *bolt.Tx, cb func(*ChannelEdge) error) error {
|
||||||
|
func (l *LightningNode) ForEachChannel(tx *bolt.Tx, cb func(*ChannelEdgeInfo, *ChannelEdgePolicy) error) error {
|
||||||
// TODO(roasbeef): remove the option to pass in a transaction after
|
// TODO(roasbeef): remove the option to pass in a transaction after
|
||||||
// all?
|
// all?
|
||||||
nodePub := l.PubKey.SerializeCompressed()
|
nodePub := l.PubKey.SerializeCompressed()
|
||||||
@ -923,6 +920,10 @@ func (l *LightningNode) ForEachChannel(tx *bolt.Tx, cb func(*ChannelEdge) error)
|
|||||||
if edges == nil {
|
if edges == nil {
|
||||||
return ErrGraphNotFound
|
return ErrGraphNotFound
|
||||||
}
|
}
|
||||||
|
edgeIndex := edges.Bucket(edgeIndexBucket)
|
||||||
|
if edgeIndex == nil {
|
||||||
|
return ErrGraphNoEdgesFound
|
||||||
|
}
|
||||||
|
|
||||||
// In order to reach all the edges for this node, we take
|
// In order to reach all the edges for this node, we take
|
||||||
// advantage of the construction of the key-space within the
|
// advantage of the construction of the key-space within the
|
||||||
@ -946,15 +947,21 @@ func (l *LightningNode) ForEachChannel(tx *bolt.Tx, cb func(*ChannelEdge) error)
|
|||||||
// edge info and fetch the outgoing node in order to
|
// edge info and fetch the outgoing node in order to
|
||||||
// retrieve the full channel edge.
|
// retrieve the full channel edge.
|
||||||
edgeReader := bytes.NewReader(edgeInfo)
|
edgeReader := bytes.NewReader(edgeInfo)
|
||||||
edge, err := deserializeChannelEdge(edgeReader, nodes)
|
edgePolicy, err := deserializeChanEdgePolicy(edgeReader, nodes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
edgePolicy.db = l.db
|
||||||
|
edgePolicy.Node.db = l.db
|
||||||
|
|
||||||
|
chanID := nodeEdge[33:]
|
||||||
|
edgeInfo, err := fetchChanEdgeInfo(edgeIndex, chanID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
edge.db = l.db
|
|
||||||
edge.Node.db = l.db
|
|
||||||
|
|
||||||
// Finally, we execute the callback.
|
// Finally, we execute the callback.
|
||||||
if err := cb(edge); err != nil {
|
if err := cb(edgeInfo, edgePolicy); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -973,36 +980,111 @@ func (l *LightningNode) ForEachChannel(tx *bolt.Tx, cb func(*ChannelEdge) error)
|
|||||||
return traversal(tx)
|
return traversal(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChannelEdge represents a *directed* edge within the channel graph. For each
|
// ChannelEdgeInfo represents a fully authenticated channel along with all its
|
||||||
// channel in the database, there are two distinct edges: one for each possible
|
// unique attributes. Once an authenticated channel announcement has been
|
||||||
// direction of travel along the channel. The edges themselves hold information
|
// processed on the network, then a instance of ChannelEdgeInfo encapsulating
|
||||||
// concerning fees, and minimum time-lock information which is utilized during
|
// the channels attributes is stored. The other portions relevant to routing
|
||||||
// path finding.
|
// policy of a channel are stored within a ChannelEdgePolicy for each direction
|
||||||
type ChannelEdge struct {
|
// of the channel.
|
||||||
|
type ChannelEdgeInfo struct {
|
||||||
// ChannelID is the unique channel ID for the channel. The first 3
|
// ChannelID is the unique channel ID for the channel. The first 3
|
||||||
// bytes are the block height, the next 3 the index within the block,
|
// bytes are the block height, the next 3 the index within the block,
|
||||||
// and the last 2 bytes are the output index for the channel.
|
// and the last 2 bytes are the output index for the channel.
|
||||||
// TODO(roasbeef): spell out and use index of channel ID to do fast look
|
|
||||||
// ups?
|
|
||||||
ChannelID uint64
|
ChannelID uint64
|
||||||
|
|
||||||
|
// NodeKey1 is the identity public key of the "first" node that was
|
||||||
|
// involved in the creation of this channel. A node is considered
|
||||||
|
// "first" if the lexicographical ordering the its serialized public
|
||||||
|
// key is "smaller" than that of the other node involved in channel
|
||||||
|
// creation.
|
||||||
|
NodeKey1 *btcec.PublicKey
|
||||||
|
|
||||||
|
// NodeKey2 is the identity public key of the "second" node that was
|
||||||
|
// involved in the creation of this channel. A node is considered
|
||||||
|
// "second" if the lexicographical ordering the its serialized public
|
||||||
|
// key is "larger" than that of the other node involved in channel
|
||||||
|
// creation.
|
||||||
|
NodeKey2 *btcec.PublicKey
|
||||||
|
|
||||||
|
// BitcoinKey1 is the Bitcoin multi-sig key belonging to the first
|
||||||
|
// node, that was involved in the funding transaction that originally
|
||||||
|
// created the channel that this struct represents.
|
||||||
|
BitcoinKey1 *btcec.PublicKey
|
||||||
|
|
||||||
|
// BitcoinKey2 is the Bitcoin multi-sig key belonging to the second
|
||||||
|
// node, that was involved in the funding transaction that originally
|
||||||
|
// created the channel that this struct represents.
|
||||||
|
BitcoinKey2 *btcec.PublicKey
|
||||||
|
|
||||||
|
// Features is an opaque byte slice that encodes the set of channel
|
||||||
|
// specific features that this channel edge supports.
|
||||||
|
Features []byte
|
||||||
|
|
||||||
|
// AuthProof is the authentication proof for this channel. This proof
|
||||||
|
// contains a set of signatures binding four identities, which attests
|
||||||
|
// to the legitimacy of the advertised channel.
|
||||||
|
AuthProof *ChannelAuthProof
|
||||||
|
|
||||||
// ChannelPoint is the funding outpoint of the channel. This can be
|
// ChannelPoint is the funding outpoint of the channel. This can be
|
||||||
// used to uniquely identify the channel within the channel graph.
|
// used to uniquely identify the channel within the channel graph.
|
||||||
ChannelPoint wire.OutPoint
|
ChannelPoint wire.OutPoint
|
||||||
|
|
||||||
|
// Capacity is the total capacity of the channel, this is determined by
|
||||||
|
// the value output in the outpoint that created this channel.
|
||||||
|
Capacity btcutil.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChannelAuthProof is the authentication proof (the signature portion) for a
|
||||||
|
// channel. Using the four signatures contained in the struct, and some
|
||||||
|
// axillary knowledge (the funding script, node identities, and outpoint) nodes
|
||||||
|
// on the network are able to validate the authenticity and existence of a
|
||||||
|
// channel. Each of these signatures signs the following digest: chanID ||
|
||||||
|
// nodeID1 || nodeID2 || bitcoinKey1|| bitcoinKey2 || 2-byte-feature-len ||
|
||||||
|
// features.
|
||||||
|
type ChannelAuthProof struct {
|
||||||
|
// NodeSig1 is the signature using the identity key of the node that is
|
||||||
|
// first in a lexicographical ordering of the serialized public keys of
|
||||||
|
// the two nodes that created the channel.
|
||||||
|
NodeSig1 *btcec.Signature
|
||||||
|
|
||||||
|
// NodeSig2 is the signature using the identity key of the node that is
|
||||||
|
// second in a lexicographical ordering of the serialized public keys
|
||||||
|
// of the two nodes that created the channel.
|
||||||
|
NodeSig2 *btcec.Signature
|
||||||
|
|
||||||
|
// BitcoinSig1 is the signature using the public key of the first node
|
||||||
|
// that was used in the channel's multi-sig output.
|
||||||
|
BitcoinSig1 *btcec.Signature
|
||||||
|
|
||||||
|
// BitcoinSig2 is the signature using the public key of the second node
|
||||||
|
// that was used in the channel's mult-sig output.
|
||||||
|
BitcoinSig2 *btcec.Signature
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChannelEdgePolicy represents a *directed* edge within the channel graph. For
|
||||||
|
// each channel in the database, there are two distinct edges: one for each
|
||||||
|
// possible direction of travel along the channel. The edges themselves hold
|
||||||
|
// information concerning fees, and minimum time-lock information which is
|
||||||
|
// utilized during path finding.
|
||||||
|
type ChannelEdgePolicy struct {
|
||||||
|
// ChannelID is the unique channel ID for the channel. The first 3
|
||||||
|
// bytes are the block height, the next 3 the index within the block,
|
||||||
|
// and the last 2 bytes are the output index for the channel.
|
||||||
|
ChannelID uint64
|
||||||
|
|
||||||
// LastUpdate is the last time an authenticated edge for this channel
|
// LastUpdate is the last time an authenticated edge for this channel
|
||||||
// was received.
|
// was received.
|
||||||
LastUpdate time.Time
|
LastUpdate time.Time
|
||||||
|
|
||||||
// Flags is a bitfield which signals the capabilities of the channel as
|
// Flags is a bitfield which signals the capabilities of the channel as
|
||||||
// well as the directe edge this update applies to.
|
// well as the directed edge this update applies to.
|
||||||
// TODO(roasbeef): make into wire struct
|
// TODO(roasbeef): make into wire struct
|
||||||
Flags uint16
|
Flags uint16
|
||||||
|
|
||||||
// Expiry is the number of blocks this node will subtract from the
|
// TimeLockDelta is the number of blocks this node will subtract from
|
||||||
// expiry of an incoming HTLC. This value expresses the time buffer the
|
// the expiry of an incoming HTLC. This value expresses the time buffer
|
||||||
// node would like to HTLC exchanges.
|
// the node would like to HTLC exchanges.
|
||||||
Expiry uint16
|
TimeLockDelta uint16
|
||||||
|
|
||||||
// MinHTLC is the smallest value HTLC this node will accept, expressed
|
// MinHTLC is the smallest value HTLC this node will accept, expressed
|
||||||
// in millisatoshi.
|
// in millisatoshi.
|
||||||
@ -1016,10 +1098,6 @@ type ChannelEdge struct {
|
|||||||
// HTLCs for each millionth of a satoshi forwarded.
|
// HTLCs for each millionth of a satoshi forwarded.
|
||||||
FeeProportionalMillionths btcutil.Amount
|
FeeProportionalMillionths btcutil.Amount
|
||||||
|
|
||||||
// Capacity is the total capacity of the channel, this is determined by
|
|
||||||
// the value output in the outpoint that created this channel.
|
|
||||||
Capacity btcutil.Amount
|
|
||||||
|
|
||||||
// Node is the LightningNode that this directed edge leads to. Using
|
// Node is the LightningNode that this directed edge leads to. Using
|
||||||
// this pointer the channel graph can further be traversed.
|
// this pointer the channel graph can further be traversed.
|
||||||
Node *LightningNode
|
Node *LightningNode
|
||||||
@ -1029,11 +1107,15 @@ type ChannelEdge struct {
|
|||||||
|
|
||||||
// FetchChannelEdgesByOutpoint attempts to lookup the two directed edges for
|
// FetchChannelEdgesByOutpoint attempts to lookup the two directed edges for
|
||||||
// the channel identified by the funding outpoint. If the channel can't be
|
// the channel identified by the funding outpoint. If the channel can't be
|
||||||
// found, then ErrEdgeNotFound is returned.
|
// found, then ErrEdgeNotFound is returned. A struct which houses the general
|
||||||
func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint) (*ChannelEdge, *ChannelEdge, error) {
|
// information for the channel itself is returned as well as two structs that
|
||||||
|
// contain the routing policies for the channel in either direction.
|
||||||
|
func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint) (*ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
edge1 *ChannelEdge
|
edgeInfo *ChannelEdgeInfo
|
||||||
edge2 *ChannelEdge
|
policy1 *ChannelEdgePolicy
|
||||||
|
policy2 *ChannelEdgePolicy
|
||||||
)
|
)
|
||||||
|
|
||||||
err := c.db.Update(func(tx *bolt.Tx) error {
|
err := c.db.Update(func(tx *bolt.Tx) error {
|
||||||
@ -1071,29 +1153,45 @@ func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint) (*ChannelE
|
|||||||
return ErrEdgeNotFound
|
return ErrEdgeNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
e1, e2, err := fetchEdges(edgeIndex, edges, nodes, chanID, c.db)
|
// If the channel is found to exists, then we'll first retrieve
|
||||||
|
// the general information for the channel.
|
||||||
|
edge, err := fetchChanEdgeInfo(edgeIndex, chanID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
edgeInfo = edge
|
||||||
|
|
||||||
|
// Once we have the information about the channels' parameters,
|
||||||
|
// we'll fetch the routing policies for each for the directed
|
||||||
|
// edges.
|
||||||
|
e1, e2, err := fetchChanEdgePolicies(edgeIndex, edges, nodes,
|
||||||
|
chanID, c.db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
edge1 = e1
|
policy1 = e1
|
||||||
edge2 = e2
|
policy2 = e2
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return edge1, edge2, nil
|
return edgeInfo, policy1, policy2, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchChannelEdgesByID attempts to lookup the two directed edges for the
|
// FetchChannelEdgesByID attempts to lookup the two directed edges for the
|
||||||
// channel identified by the channel ID. If the channel can't be found, then
|
// channel identified by the channel ID. If the channel can't be found, then
|
||||||
// ErrEdgeNotFound is returned.
|
// ErrEdgeNotFound is returned. A struct which houses the general information
|
||||||
func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64) (*ChannelEdge, *ChannelEdge, error) {
|
// for the channel itself is returned as well as two structs that contain the
|
||||||
|
// routing policies for the channel in either direction.
|
||||||
|
func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64) (*ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
edge1 *ChannelEdge
|
edgeInfo *ChannelEdgeInfo
|
||||||
edge2 *ChannelEdge
|
policy1 *ChannelEdgePolicy
|
||||||
|
policy2 *ChannelEdgePolicy
|
||||||
channelID [8]byte
|
channelID [8]byte
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1118,26 +1216,33 @@ func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64) (*ChannelEdge, *Chan
|
|||||||
}
|
}
|
||||||
|
|
||||||
byteOrder.PutUint64(channelID[:], chanID)
|
byteOrder.PutUint64(channelID[:], chanID)
|
||||||
e1, e2, err := fetchEdges(edgeIndex, edges, nodes,
|
|
||||||
|
edge, err := fetchChanEdgeInfo(edgeIndex, channelID[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
edgeInfo = edge
|
||||||
|
|
||||||
|
e1, e2, err := fetchChanEdgePolicies(edgeIndex, edges, nodes,
|
||||||
channelID[:], c.db)
|
channelID[:], c.db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
edge1 = e1
|
policy1 = e1
|
||||||
edge2 = e2
|
policy2 = e2
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return edge1, edge2, nil
|
return edgeInfo, policy1, policy2, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChannelEdge returns a new blank ChannelEdge.
|
// NewChannelEdgePolicy returns a new blank ChannelEdgePolicy.
|
||||||
func (c *ChannelGraph) NewChannelEdge() *ChannelEdge {
|
func (c *ChannelGraph) NewChannelEdgePolicy() *ChannelEdgePolicy {
|
||||||
return &ChannelEdge{db: c.db}
|
return &ChannelEdgePolicy{db: c.db}
|
||||||
}
|
}
|
||||||
|
|
||||||
func putLightningNode(nodeBucket *bolt.Bucket, aliasBucket *bolt.Bucket, node *LightningNode) error {
|
func putLightningNode(nodeBucket *bolt.Bucket, aliasBucket *bolt.Bucket, node *LightningNode) error {
|
||||||
@ -1243,7 +1348,145 @@ func deserializeLightningNode(r io.Reader) (*LightningNode, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func putChannelEdge(edges *bolt.Bucket, edge *ChannelEdge, from, to []byte) error {
|
func putChanEdgeInfo(edgeIndex *bolt.Bucket, edgeInfo *ChannelEdgeInfo, chanID [8]byte) error {
|
||||||
|
var b bytes.Buffer
|
||||||
|
|
||||||
|
if _, err := b.Write(edgeInfo.NodeKey1.SerializeCompressed()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := b.Write(edgeInfo.NodeKey2.SerializeCompressed()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := b.Write(edgeInfo.BitcoinKey1.SerializeCompressed()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := b.Write(edgeInfo.BitcoinKey2.SerializeCompressed()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := wire.WriteVarBytes(&b, 0, edgeInfo.Features); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
authProof := edgeInfo.AuthProof
|
||||||
|
if err := wire.WriteVarBytes(&b, 0, authProof.NodeSig1.Serialize()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := wire.WriteVarBytes(&b, 0, authProof.NodeSig2.Serialize()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := wire.WriteVarBytes(&b, 0, authProof.BitcoinSig1.Serialize()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := wire.WriteVarBytes(&b, 0, authProof.BitcoinSig2.Serialize()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := writeOutpoint(&b, &edgeInfo.ChannelPoint); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := binary.Write(&b, byteOrder, uint64(edgeInfo.Capacity)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := b.Write(chanID[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return edgeIndex.Put(chanID[:], b.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchChanEdgeInfo(edgeIndex *bolt.Bucket,
|
||||||
|
chanID []byte) (*ChannelEdgeInfo, error) {
|
||||||
|
|
||||||
|
edgeInfoBytes := edgeIndex.Get(chanID)
|
||||||
|
if edgeInfoBytes == nil {
|
||||||
|
return nil, ErrEdgeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
edgeInfoReader := bytes.NewReader(edgeInfoBytes)
|
||||||
|
return deserializeChanEdgeInfo(edgeInfoReader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deserializeChanEdgeInfo(r io.Reader) (*ChannelEdgeInfo, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
pubKeyBytes [33]byte
|
||||||
|
edgeInfo = &ChannelEdgeInfo{}
|
||||||
|
)
|
||||||
|
|
||||||
|
readKey := func() (*btcec.PublicKey, error) {
|
||||||
|
if _, err := io.ReadFull(r, pubKeyBytes[:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return btcec.ParsePubKey(pubKeyBytes[:], btcec.S256())
|
||||||
|
}
|
||||||
|
|
||||||
|
edgeInfo.NodeKey1, err = readKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
edgeInfo.NodeKey2, err = readKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
edgeInfo.BitcoinKey1, err = readKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
edgeInfo.BitcoinKey2, err = readKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
edgeInfo.Features, err = wire.ReadVarBytes(r, 0, 900, "features")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
edgeInfo.AuthProof = &ChannelAuthProof{}
|
||||||
|
|
||||||
|
readSig := func() (*btcec.Signature, error) {
|
||||||
|
sigBytes, err := wire.ReadVarBytes(r, 0, 80, "sigs")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return btcec.ParseSignature(sigBytes, btcec.S256())
|
||||||
|
}
|
||||||
|
|
||||||
|
edgeInfo.AuthProof.NodeSig1, err = readSig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
edgeInfo.AuthProof.NodeSig2, err = readSig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
edgeInfo.AuthProof.BitcoinSig1, err = readSig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
edgeInfo.AuthProof.BitcoinSig2, err = readSig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
edgeInfo.ChannelPoint = wire.OutPoint{}
|
||||||
|
if err := readOutpoint(r, &edgeInfo.ChannelPoint); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := binary.Read(r, byteOrder, &edgeInfo.Capacity); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := binary.Read(r, byteOrder, &edgeInfo.ChannelID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return edgeInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func putChanEdgePolicy(edges *bolt.Bucket, edge *ChannelEdgePolicy, from, to []byte) error {
|
||||||
var edgeKey [33 + 8]byte
|
var edgeKey [33 + 8]byte
|
||||||
copy(edgeKey[:], from)
|
copy(edgeKey[:], from)
|
||||||
byteOrder.PutUint64(edgeKey[33:], edge.ChannelID)
|
byteOrder.PutUint64(edgeKey[33:], edge.ChannelID)
|
||||||
@ -1254,10 +1497,6 @@ func putChannelEdge(edges *bolt.Bucket, edge *ChannelEdge, from, to []byte) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := writeOutpoint(&b, &edge.ChannelPoint); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var scratch [8]byte
|
var scratch [8]byte
|
||||||
updateUnix := uint64(edge.LastUpdate.Unix())
|
updateUnix := uint64(edge.LastUpdate.Unix())
|
||||||
byteOrder.PutUint64(scratch[:], updateUnix)
|
byteOrder.PutUint64(scratch[:], updateUnix)
|
||||||
@ -1268,7 +1507,7 @@ func putChannelEdge(edges *bolt.Bucket, edge *ChannelEdge, from, to []byte) erro
|
|||||||
if err := binary.Write(&b, byteOrder, edge.Flags); err != nil {
|
if err := binary.Write(&b, byteOrder, edge.Flags); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := binary.Write(&b, byteOrder, edge.Expiry); err != nil {
|
if err := binary.Write(&b, byteOrder, edge.TimeLockDelta); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := binary.Write(&b, byteOrder, uint64(edge.MinHTLC)); err != nil {
|
if err := binary.Write(&b, byteOrder, uint64(edge.MinHTLC)); err != nil {
|
||||||
@ -1280,9 +1519,6 @@ func putChannelEdge(edges *bolt.Bucket, edge *ChannelEdge, from, to []byte) erro
|
|||||||
if err := binary.Write(&b, byteOrder, uint64(edge.FeeProportionalMillionths)); err != nil {
|
if err := binary.Write(&b, byteOrder, uint64(edge.FeeProportionalMillionths)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := binary.Write(&b, byteOrder, uint64(edge.Capacity)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := b.Write(to); err != nil {
|
if _, err := b.Write(to); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -1291,8 +1527,26 @@ func putChannelEdge(edges *bolt.Bucket, edge *ChannelEdge, from, to []byte) erro
|
|||||||
return edges.Put(edgeKey[:], b.Bytes()[:])
|
return edges.Put(edgeKey[:], b.Bytes()[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchEdges(edgeIndex *bolt.Bucket, edges *bolt.Bucket, nodes *bolt.Bucket,
|
func fetchChanEdgePolicy(edges *bolt.Bucket, chanID []byte,
|
||||||
chanID []byte, db *DB) (*ChannelEdge, *ChannelEdge, error) {
|
nodePub []byte, nodes *bolt.Bucket) (*ChannelEdgePolicy, error) {
|
||||||
|
|
||||||
|
var edgeKey [33 + 8]byte
|
||||||
|
copy(edgeKey[:], nodePub)
|
||||||
|
copy(edgeKey[33:], chanID[:])
|
||||||
|
|
||||||
|
edgeBytes := edges.Get(edgeKey[:])
|
||||||
|
if edgeBytes == nil {
|
||||||
|
return nil, ErrEdgeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
edgeReader := bytes.NewReader(edgeBytes)
|
||||||
|
|
||||||
|
return deserializeChanEdgePolicy(edgeReader, nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchChanEdgePolicies(edgeIndex *bolt.Bucket, edges *bolt.Bucket,
|
||||||
|
nodes *bolt.Bucket, chanID []byte,
|
||||||
|
db *DB) (*ChannelEdgePolicy, *ChannelEdgePolicy, error) {
|
||||||
|
|
||||||
edgeInfo := edgeIndex.Get(chanID)
|
edgeInfo := edgeIndex.Get(chanID)
|
||||||
if edgeInfo == nil {
|
if edgeInfo == nil {
|
||||||
@ -1303,7 +1557,7 @@ func fetchEdges(edgeIndex *bolt.Bucket, edges *bolt.Bucket, nodes *bolt.Bucket,
|
|||||||
// information. We only propagate the error here and below if it's
|
// information. We only propagate the error here and below if it's
|
||||||
// something other than edge non-existence.
|
// something other than edge non-existence.
|
||||||
node1Pub := edgeInfo[:33]
|
node1Pub := edgeInfo[:33]
|
||||||
edge1, err := fetchChannelEdge(edges, chanID, node1Pub, nodes)
|
edge1, err := fetchChanEdgePolicy(edges, chanID, node1Pub, nodes)
|
||||||
if err != nil && err != ErrEdgeNotFound {
|
if err != nil && err != ErrEdgeNotFound {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -1317,8 +1571,8 @@ func fetchEdges(edgeIndex *bolt.Bucket, edges *bolt.Bucket, nodes *bolt.Bucket,
|
|||||||
|
|
||||||
// Similarly, the second node is contained within the latter
|
// Similarly, the second node is contained within the latter
|
||||||
// half of the edge information.
|
// half of the edge information.
|
||||||
node2Pub := edgeInfo[33:]
|
node2Pub := edgeInfo[33:67]
|
||||||
edge2, err := fetchChannelEdge(edges, chanID, node2Pub, nodes)
|
edge2, err := fetchChanEdgePolicy(edges, chanID, node2Pub, nodes)
|
||||||
if err != nil && err != ErrEdgeNotFound {
|
if err != nil && err != ErrEdgeNotFound {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -1331,35 +1585,15 @@ func fetchEdges(edgeIndex *bolt.Bucket, edges *bolt.Bucket, nodes *bolt.Bucket,
|
|||||||
return edge1, edge2, nil
|
return edge1, edge2, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchChannelEdge(edges *bolt.Bucket, chanID []byte,
|
func deserializeChanEdgePolicy(r io.Reader,
|
||||||
nodePub []byte, nodes *bolt.Bucket) (*ChannelEdge, error) {
|
nodes *bolt.Bucket) (*ChannelEdgePolicy, error) {
|
||||||
|
|
||||||
var edgeKey [33 + 8]byte
|
edge := &ChannelEdgePolicy{}
|
||||||
copy(edgeKey[:], nodePub)
|
|
||||||
copy(edgeKey[33:], chanID[:])
|
|
||||||
|
|
||||||
edgeBytes := edges.Get(edgeKey[:])
|
|
||||||
if edgeBytes == nil {
|
|
||||||
return nil, ErrEdgeNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
edgeReader := bytes.NewReader(edgeBytes)
|
|
||||||
|
|
||||||
return deserializeChannelEdge(edgeReader, nodes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func deserializeChannelEdge(r io.Reader, nodes *bolt.Bucket) (*ChannelEdge, error) {
|
|
||||||
edge := &ChannelEdge{}
|
|
||||||
|
|
||||||
if err := binary.Read(r, byteOrder, &edge.ChannelID); err != nil {
|
if err := binary.Read(r, byteOrder, &edge.ChannelID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
edge.ChannelPoint = wire.OutPoint{}
|
|
||||||
if err := readOutpoint(r, &edge.ChannelPoint); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var scratch [8]byte
|
var scratch [8]byte
|
||||||
if _, err := r.Read(scratch[:]); err != nil {
|
if _, err := r.Read(scratch[:]); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1370,7 +1604,7 @@ func deserializeChannelEdge(r io.Reader, nodes *bolt.Bucket) (*ChannelEdge, erro
|
|||||||
if err := binary.Read(r, byteOrder, &edge.Flags); err != nil {
|
if err := binary.Read(r, byteOrder, &edge.Flags); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := binary.Read(r, byteOrder, &edge.Expiry); err != nil {
|
if err := binary.Read(r, byteOrder, &edge.TimeLockDelta); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1390,11 +1624,6 @@ func deserializeChannelEdge(r io.Reader, nodes *bolt.Bucket) (*ChannelEdge, erro
|
|||||||
}
|
}
|
||||||
edge.FeeProportionalMillionths = btcutil.Amount(n)
|
edge.FeeProportionalMillionths = btcutil.Amount(n)
|
||||||
|
|
||||||
if err := binary.Read(r, byteOrder, &n); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
edge.Capacity = btcutil.Amount(n)
|
|
||||||
|
|
||||||
var pub [33]byte
|
var pub [33]byte
|
||||||
if _, err := r.Read(pub[:]); err != nil {
|
if _, err := r.Read(pub[:]); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Loading…
Reference in New Issue
Block a user