@@ -138,13 +138,26 @@ var _ NetworkPeerBootstrapper = (*ChannelGraphBootstrapper)(nil)
138
138
// backed by an active autopilot.ChannelGraph instance. This type of network
139
139
// peer bootstrapper will use the authenticated nodes within the known channel
140
140
// graph to bootstrap connections.
141
- func NewGraphBootstrapper (cg autopilot.ChannelGraph ) ( NetworkPeerBootstrapper ,
142
- error ) {
141
+ func NewGraphBootstrapper (cg autopilot.ChannelGraph ,
142
+ deterministicSampling bool ) ( NetworkPeerBootstrapper , error ) {
143
143
144
- hashAccumulator , err := newRandomHashAccumulator ()
145
- if err != nil {
146
- return nil , fmt .Errorf ("unable to create hash accumulator: %w" ,
147
- err )
144
+ var (
145
+ hashAccumulator hashAccumulator
146
+ err error
147
+ )
148
+ if deterministicSampling {
149
+ // If we're using deterministic sampling, then we'll use a
150
+ // no-op hash accumulator that will always return false for
151
+ // skipNode.
152
+ hashAccumulator = newNoOpHashAccumulator ()
153
+ } else {
154
+ // Otherwise, we'll use a random hash accumulator to sample
155
+ // nodes from the channel graph.
156
+ hashAccumulator , err = newRandomHashAccumulator ()
157
+ if err != nil {
158
+ return nil , fmt .Errorf ("unable to create hash " +
159
+ "accumulator: %w" , err )
160
+ }
148
161
}
149
162
150
163
return & ChannelGraphBootstrapper {
@@ -602,3 +615,29 @@ func (r *randomHashAccumulator) rotate() {
602
615
func (r * randomHashAccumulator ) skipNode (pub route.Vertex ) bool {
603
616
return bytes .Compare (r .hash [:], pub [1 :]) > 0
604
617
}
618
+
619
+ // noOpHashAccumulator is a no-op implementation of the hashAccumulator
620
+ // interface. This is used when we want deterministic behavior and don't
621
+ // want to sample nodes randomly from the channel graph.
622
+ type noOpHashAccumulator struct {}
623
+
624
+ // newNoOpHashAccumulator returns a new instance of a noOpHashAccumulator.
625
+ func newNoOpHashAccumulator () * noOpHashAccumulator {
626
+ return & noOpHashAccumulator {}
627
+ }
628
+
629
+ // rotate is a no-op for the noOpHashAccumulator.
630
+ //
631
+ // NOTE: this is part of the hashAccumulator interface.
632
+ func (* noOpHashAccumulator ) rotate () {}
633
+
634
+ // skipNode always returns false, meaning that no nodes will be skipped.
635
+ //
636
+ // NOTE: this is part of the hashAccumulator interface.
637
+ func (* noOpHashAccumulator ) skipNode (route.Vertex ) bool {
638
+ return false
639
+ }
640
+
641
+ // A compile-time assertion to ensure that noOpHashAccumulator meets the
642
+ // hashAccumulator interface.
643
+ var _ hashAccumulator = (* noOpHashAccumulator )(nil )
0 commit comments