Skip to content

Commit cd37d1a

Browse files
guggerobhandras
authored andcommitted
chainnotifier: add re-org chan option to RegisterConfirmationsNtfn
With this commit we add the WithReOrgChan functional option to the RegisterConfirmationsNtfn method that allows a caller to be notified about a chain re-organization of a transaction. Using WithReOrgChan() might be a breaking change to the caller, as the behavior of the RegisterConfirmationsNtfn changes: Before, the notification channel would not continue sending updates after a confirmation event was received. When enabling WithReOrgChan(), the notification channel will continue sending updates even after a first confirmation, and will also send on the provided re-org channel if a re-org happens. After a re-org a new confirmation event is sent on the notification channel once the transaction is included in another block again. To allow a caller to reliably make sure a transaction reaches a certain safe depth in the chain, it is recommended to use RegisterConfirmationsNtfn with numConfs=1 but then keep the notification channel open until the transaction reaches the desired number of confirmations (or reac to re-org events if they happen).
1 parent 30cc4c5 commit cd37d1a

File tree

1 file changed

+49
-13
lines changed

1 file changed

+49
-13
lines changed

chainnotifier_client.go

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ type notifierOptions struct {
1919
// includeBlock if true, then the dispatched confirmation notification
2020
// will include the block that mined the transaction.
2121
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{}
2230
}
2331

2432
// defaultNotifierOptions returns the set of default options for the notifier.
@@ -38,15 +46,27 @@ func WithIncludeBlock() NotifierOption {
3846
}
3947
}
4048

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+
4161
// ChainNotifierClient exposes base lightning functionality.
4262
type ChainNotifierClient interface {
4363
RegisterBlockEpochNtfn(ctx context.Context) (
4464
chan int32, chan error, error)
4565

4666
RegisterConfirmationsNtfn(ctx context.Context, txid *chainhash.Hash,
4767
pkScript []byte, numConfs, heightHint int32,
48-
opts ...NotifierOption) (
49-
chan *chainntnfs.TxConfirmation, chan error, error)
68+
opts ...NotifierOption) (chan *chainntnfs.TxConfirmation,
69+
chan error, error)
5070

5171
RegisterSpendNtfn(ctx context.Context,
5272
outpoint *wire.OutPoint, pkScript []byte, heightHint int32) (
@@ -153,8 +173,8 @@ func (s *chainNotifierClient) RegisterSpendNtfn(ctx context.Context,
153173

154174
func (s *chainNotifierClient) RegisterConfirmationsNtfn(ctx context.Context,
155175
txid *chainhash.Hash, pkScript []byte, numConfs, heightHint int32,
156-
optFuncs ...NotifierOption) (
157-
chan *chainntnfs.TxConfirmation, chan error, error) {
176+
optFuncs ...NotifierOption) (chan *chainntnfs.TxConfirmation,
177+
chan error, error) {
158178

159179
opts := defaultNotifierOptions()
160180
for _, optFunc := range optFuncs {
@@ -166,8 +186,7 @@ func (s *chainNotifierClient) RegisterConfirmationsNtfn(ctx context.Context,
166186
txidSlice = txid[:]
167187
}
168188
confStream, err := s.client.RegisterConfirmationsNtfn(
169-
s.chainMac.WithMacaroonAuth(ctx),
170-
&chainrpc.ConfRequest{
189+
s.chainMac.WithMacaroonAuth(ctx), &chainrpc.ConfRequest{
171190
Script: pkScript,
172191
NumConfs: uint32(numConfs),
173192
HeightHint: uint32(heightHint),
@@ -195,7 +214,7 @@ func (s *chainNotifierClient) RegisterConfirmationsNtfn(ctx context.Context,
195214
}
196215

197216
switch c := confEvent.Event.(type) {
198-
// Script confirmed
217+
// Script confirmed.
199218
case *chainrpc.ConfEvent_Conf:
200219
tx, err := decodeTx(c.Conf.RawTx)
201220
if err != nil {
@@ -205,7 +224,9 @@ func (s *chainNotifierClient) RegisterConfirmationsNtfn(ctx context.Context,
205224

206225
var block *wire.MsgBlock
207226
if opts.includeBlock {
208-
block, err = decodeBlock(c.Conf.RawBlock)
227+
block, err = decodeBlock(
228+
c.Conf.RawBlock,
229+
)
209230
if err != nil {
210231
errChan <- err
211232
return
@@ -227,10 +248,26 @@ func (s *chainNotifierClient) RegisterConfirmationsNtfn(ctx context.Context,
227248
TxIndex: c.Conf.TxIndex,
228249
Block: block,
229250
}
230-
return
231251

232-
// 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.
233263
case *chainrpc.ConfEvent_Reorg:
264+
if opts.reOrgChan != nil {
265+
select {
266+
case opts.reOrgChan <- struct{}{}:
267+
case <-ctx.Done():
268+
return
269+
}
270+
}
234271
continue
235272

236273
// Nil event, should never happen.
@@ -240,9 +277,8 @@ func (s *chainNotifierClient) RegisterConfirmationsNtfn(ctx context.Context,
240277

241278
// Unexpected type.
242279
default:
243-
errChan <- fmt.Errorf(
244-
"conf event has unexpected type",
245-
)
280+
errChan <- fmt.Errorf("conf event has " +
281+
"unexpected type")
246282
return
247283
}
248284
}

0 commit comments

Comments
 (0)