/ htlcswitch / held_htlc_set.go
held_htlc_set.go
 1  package htlcswitch
 2  
 3  import (
 4  	"errors"
 5  	"fmt"
 6  
 7  	"github.com/lightningnetwork/lnd/graph/db/models"
 8  )
 9  
10  // heldHtlcSet keeps track of outstanding intercepted forwards. It exposes
11  // several methods to manipulate the underlying map structure in a consistent
12  // way.
13  type heldHtlcSet struct {
14  	set map[models.CircuitKey]InterceptedForward
15  }
16  
17  func newHeldHtlcSet() *heldHtlcSet {
18  	return &heldHtlcSet{
19  		set: make(map[models.CircuitKey]InterceptedForward),
20  	}
21  }
22  
23  // forEach iterates over all held forwards and calls the given callback for each
24  // of them.
25  func (h *heldHtlcSet) forEach(cb func(InterceptedForward)) {
26  	for _, fwd := range h.set {
27  		cb(fwd)
28  	}
29  }
30  
31  // popAll calls the callback for each forward and removes them from the set.
32  func (h *heldHtlcSet) popAll(cb func(InterceptedForward)) {
33  	for _, fwd := range h.set {
34  		cb(fwd)
35  	}
36  
37  	h.set = make(map[models.CircuitKey]InterceptedForward)
38  }
39  
40  // popAutoFails calls the callback for each forward that has an auto-fail height
41  // equal or less then the specified pop height and removes them from the set.
42  func (h *heldHtlcSet) popAutoFails(height uint32, cb func(InterceptedForward)) {
43  	for key, fwd := range h.set {
44  		if uint32(fwd.Packet().AutoFailHeight) > height {
45  			continue
46  		}
47  
48  		cb(fwd)
49  
50  		delete(h.set, key)
51  	}
52  }
53  
54  // pop returns the specified forward and removes it from the set.
55  func (h *heldHtlcSet) pop(key models.CircuitKey) (InterceptedForward, error) {
56  	intercepted, ok := h.set[key]
57  	if !ok {
58  		return nil, fmt.Errorf("fwd %v not found", key)
59  	}
60  
61  	delete(h.set, key)
62  
63  	return intercepted, nil
64  }
65  
66  // exists tests whether the specified forward is part of the set.
67  func (h *heldHtlcSet) exists(key models.CircuitKey) bool {
68  	_, ok := h.set[key]
69  
70  	return ok
71  }
72  
73  // push adds the specified forward to the set. An error is returned if the
74  // forward exists already.
75  func (h *heldHtlcSet) push(key models.CircuitKey,
76  	fwd InterceptedForward) error {
77  
78  	if fwd == nil {
79  		return errors.New("nil fwd pushed")
80  	}
81  
82  	if h.exists(key) {
83  		return errors.New("htlc already exists in set")
84  	}
85  
86  	h.set[key] = fwd
87  
88  	return nil
89  }