diff --git a/channeldb/graph.go b/channeldb/graph.go index 2eddb3773..29ab3c4be 100644 --- a/channeldb/graph.go +++ b/channeldb/graph.go @@ -632,11 +632,14 @@ func (c *ChannelGraph) FetchLightningNode(pub *btcec.PublicKey) (*LightningNode, // ForEachChannel iterates through all the outgoing channel edges from this // node, executing the passed callback with each edge as its sole argument. If // the callback returns an error, then the iteration is halted with the error -// propagated back up to the caller. -func (l *LightningNode) ForEachChannel(cb func(*ChannelEdge) error) error { +// propagated back up to the caller. If the caller wishes to re-use an existing +// boltdb transaction, then it should be passed as the first argument. +// Otherwise the first argument should be nil and a fresh transaction will be +// created to execute the graph traversal. +func (l *LightningNode) ForEachChannel(tx *bolt.Tx, cb func(*ChannelEdge) error) error { nodePub := l.PubKey.SerializeCompressed() - return l.db.View(func(tx *bolt.Tx) error { + traversal := func(tx *bolt.Tx) error { nodes := tx.Bucket(nodeBucket) if nodes == nil { return ErrGraphNotFound @@ -682,7 +685,17 @@ func (l *LightningNode) ForEachChannel(cb func(*ChannelEdge) error) error { } return nil - }) + } + + // If no transaction was provided, then we'll create a new transaction + // to execute the transaction within. + if tx == nil { + return l.db.View(traversal) + } + + // Otherwise, we re-use the existing transaction to execute the graph + // traversal. + return traversal(tx) } // ChannelEdge represents a *directed* edge within the channel graph. For each diff --git a/channeldb/graph_test.go b/channeldb/graph_test.go index 555f7d97f..6c2380767 100644 --- a/channeldb/graph_test.go +++ b/channeldb/graph_test.go @@ -489,7 +489,7 @@ func TestGraphTraversal(t *testing.T) { // Finally, we want to test the ability to iterate over all the // outgoing channels for a particular node. numNodeChans := 0 - err = firstNode.ForEachChannel(func(c *ChannelEdge) error { + err = firstNode.ForEachChannel(nil, func(c *ChannelEdge) error { // Each each should indicate that it's outgoing (pointed // towards the second node). if !c.Node.PubKey.IsEqual(secondNode.PubKey) {