@@ -13,14 +13,60 @@ import (
1313 "google.golang.org/grpc"
1414)
1515
16+ // notifierOptions is a set of functional options that allow callers to further
17+ // modify the type of chain even notifications they receive.
18+ type notifierOptions struct {
19+ // includeBlock if true, then the dispatched confirmation notification
20+ // will include the block that mined the transaction.
21+ includeBlock bool
22+
23+ // reOrgChan if set, will be sent on if the transaction is re-organized
24+ // out of the chain. This channel being set will also imply that we
25+ // don't cancel the notification listener after having received one
26+ // confirmation event. That means the caller manually needs to cancel
27+ // the passed in context to cancel being notified once the required
28+ // number of confirmations have been reached.
29+ reOrgChan chan struct {}
30+ }
31+
32+ // defaultNotifierOptions returns the set of default options for the notifier.
33+ func defaultNotifierOptions () * notifierOptions {
34+ return & notifierOptions {}
35+ }
36+
37+ // NotifierOption is a functional option that allows a caller to modify the
38+ // events received from the notifier.
39+ type NotifierOption func (* notifierOptions )
40+
41+ // WithIncludeBlock is an optional argument that allows the caller to specify
42+ // that the block that mined a transaction should be included in the response.
43+ func WithIncludeBlock () NotifierOption {
44+ return func (o * notifierOptions ) {
45+ o .includeBlock = true
46+ }
47+ }
48+
49+ // WithReOrgChan configures a channel that will be sent on if the transaction is
50+ // re-organized out of the chain. This channel being set will also imply that we
51+ // don't cancel the notification listener after having received one confirmation
52+ // event. That means the caller manually needs to cancel the passed in context
53+ // to cancel being notified once the required number of confirmations have been
54+ // reached.
55+ func WithReOrgChan (reOrgChan chan struct {}) NotifierOption {
56+ return func (o * notifierOptions ) {
57+ o .reOrgChan = reOrgChan
58+ }
59+ }
60+
1661// ChainNotifierClient exposes base lightning functionality.
1762type ChainNotifierClient interface {
1863 RegisterBlockEpochNtfn (ctx context.Context ) (
1964 chan int32 , chan error , error )
2065
2166 RegisterConfirmationsNtfn (ctx context.Context , txid * chainhash.Hash ,
22- pkScript []byte , numConfs , heightHint int32 ) (
23- chan * chainntnfs.TxConfirmation , chan error , error )
67+ pkScript []byte , numConfs , heightHint int32 ,
68+ opts ... NotifierOption ) (chan * chainntnfs.TxConfirmation ,
69+ chan error , error )
2470
2571 RegisterSpendNtfn (ctx context.Context ,
2672 outpoint * wire.OutPoint , pkScript []byte , heightHint int32 ) (
@@ -126,20 +172,26 @@ func (s *chainNotifierClient) RegisterSpendNtfn(ctx context.Context,
126172}
127173
128174func (s * chainNotifierClient ) RegisterConfirmationsNtfn (ctx context.Context ,
129- txid * chainhash.Hash , pkScript []byte , numConfs , heightHint int32 ) (
130- chan * chainntnfs.TxConfirmation , chan error , error ) {
175+ txid * chainhash.Hash , pkScript []byte , numConfs , heightHint int32 ,
176+ optFuncs ... NotifierOption ) (chan * chainntnfs.TxConfirmation ,
177+ chan error , error ) {
178+
179+ opts := defaultNotifierOptions ()
180+ for _ , optFunc := range optFuncs {
181+ optFunc (opts )
182+ }
131183
132184 var txidSlice []byte
133185 if txid != nil {
134186 txidSlice = txid [:]
135187 }
136188 confStream , err := s .client .RegisterConfirmationsNtfn (
137- s .chainMac .WithMacaroonAuth (ctx ),
138- & chainrpc. ConfRequest {
139- Script : pkScript ,
140- NumConfs : uint32 (numConfs ),
141- HeightHint : uint32 ( heightHint ) ,
142- Txid : txidSlice ,
189+ s .chainMac .WithMacaroonAuth (ctx ), & chainrpc. ConfRequest {
190+ Script : pkScript ,
191+ NumConfs : uint32 ( numConfs ) ,
192+ HeightHint : uint32 (heightHint ),
193+ Txid : txidSlice ,
194+ IncludeBlock : opts . includeBlock ,
143195 },
144196 )
145197 if err != nil {
@@ -162,30 +214,60 @@ func (s *chainNotifierClient) RegisterConfirmationsNtfn(ctx context.Context,
162214 }
163215
164216 switch c := confEvent .Event .(type ) {
165- // Script confirmed
217+ // Script confirmed.
166218 case * chainrpc.ConfEvent_Conf :
167219 tx , err := decodeTx (c .Conf .RawTx )
168220 if err != nil {
169221 errChan <- err
170222 return
171223 }
224+
225+ var block * wire.MsgBlock
226+ if opts .includeBlock {
227+ block , err = decodeBlock (
228+ c .Conf .RawBlock ,
229+ )
230+ if err != nil {
231+ errChan <- err
232+ return
233+ }
234+ }
235+
172236 blockHash , err := chainhash .NewHash (
173237 c .Conf .BlockHash ,
174238 )
175239 if err != nil {
176240 errChan <- err
177241 return
178242 }
243+
179244 confChan <- & chainntnfs.TxConfirmation {
180245 BlockHeight : c .Conf .BlockHeight ,
181246 BlockHash : blockHash ,
182247 Tx : tx ,
183248 TxIndex : c .Conf .TxIndex ,
249+ Block : block ,
184250 }
185- return
186251
187- // Ignore reorg events, not supported.
252+ // If we're running in re-org aware mode, then
253+ // we don't return here, since we might want to
254+ // be informed about the new block we got
255+ // confirmed in after a re-org.
256+ if opts .reOrgChan == nil {
257+ return
258+ }
259+
260+ // On a re-org, we just need to signal, we don't have
261+ // any additional information. But we only signal if the
262+ // caller requested to be notified about re-orgs.
188263 case * chainrpc.ConfEvent_Reorg :
264+ if opts .reOrgChan != nil {
265+ select {
266+ case opts .reOrgChan <- struct {}{}:
267+ case <- ctx .Done ():
268+ return
269+ }
270+ }
189271 continue
190272
191273 // Nil event, should never happen.
@@ -195,9 +277,8 @@ func (s *chainNotifierClient) RegisterConfirmationsNtfn(ctx context.Context,
195277
196278 // Unexpected type.
197279 default :
198- errChan <- fmt .Errorf (
199- "conf event has unexpected type" ,
200- )
280+ errChan <- fmt .Errorf ("conf event has " +
281+ "unexpected type" )
201282 return
202283 }
203284 }
0 commit comments