• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 9915780197

13 Jul 2024 12:30AM UTC coverage: 49.268% (-9.1%) from 58.413%
9915780197

push

github

web-flow
Merge pull request #8653 from ProofOfKeags/fn-prim

DynComms [0/n]: `fn` package additions

92837 of 188433 relevant lines covered (49.27%)

1.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.59
/contractcourt/briefcase.go
1
package contractcourt
2

3
import (
4
        "bytes"
5
        "encoding/binary"
6
        "fmt"
7
        "io"
8

9
        "github.com/btcsuite/btcd/chaincfg/chainhash"
10
        "github.com/btcsuite/btcd/txscript"
11
        "github.com/btcsuite/btcd/wire"
12
        "github.com/lightningnetwork/lnd/channeldb"
13
        "github.com/lightningnetwork/lnd/input"
14
        "github.com/lightningnetwork/lnd/kvdb"
15
        "github.com/lightningnetwork/lnd/lnwallet"
16
)
17

18
// ContractResolutions is a wrapper struct around the two forms of resolutions
19
// we may need to carry out once a contract is closing: resolving the
20
// commitment output, and resolving any incoming+outgoing HTLC's still present
21
// in the commitment.
22
type ContractResolutions struct {
23
        // CommitHash is the txid of the commitment transaction.
24
        CommitHash chainhash.Hash
25

26
        // CommitResolution contains all data required to fully resolve a
27
        // commitment output.
28
        CommitResolution *lnwallet.CommitOutputResolution
29

30
        // HtlcResolutions contains all data required to fully resolve any
31
        // incoming+outgoing HTLC's present within the commitment transaction.
32
        HtlcResolutions lnwallet.HtlcResolutions
33

34
        // AnchorResolution contains the data required to sweep the anchor
35
        // output. If the channel type doesn't include anchors, the value of
36
        // this field will be nil.
37
        AnchorResolution *lnwallet.AnchorResolution
38

39
        // BreachResolution contains the data required to manage the lifecycle
40
        // of a breach in the ChannelArbitrator.
41
        BreachResolution *BreachResolution
42
}
43

44
// IsEmpty returns true if the set of resolutions is "empty". A resolution is
45
// empty if: our commitment output has been trimmed, we don't have any
46
// incoming or outgoing HTLC's active, there is no anchor output to sweep, or
47
// there are no breached outputs to resolve.
48
func (c *ContractResolutions) IsEmpty() bool {
3✔
49
        return c.CommitResolution == nil &&
3✔
50
                len(c.HtlcResolutions.IncomingHTLCs) == 0 &&
3✔
51
                len(c.HtlcResolutions.OutgoingHTLCs) == 0 &&
3✔
52
                c.AnchorResolution == nil && c.BreachResolution == nil
3✔
53
}
3✔
54

55
// ArbitratorLog is the primary source of persistent storage for the
56
// ChannelArbitrator. The log stores the current state of the
57
// ChannelArbitrator's internal state machine, any items that are required to
58
// properly make a state transition, and any unresolved contracts.
59
type ArbitratorLog interface {
60
        // TODO(roasbeef): document on interface the errors expected to be
61
        // returned
62

63
        // CurrentState returns the current state of the ChannelArbitrator. It
64
        // takes an optional database transaction, which will be used if it is
65
        // non-nil, otherwise the lookup will be done in its own transaction.
66
        CurrentState(tx kvdb.RTx) (ArbitratorState, error)
67

68
        // CommitState persists, the current state of the chain attendant.
69
        CommitState(ArbitratorState) error
70

71
        // InsertUnresolvedContracts inserts a set of unresolved contracts into
72
        // the log. The log will then persistently store each contract until
73
        // they've been swapped out, or resolved. It takes a set of report which
74
        // should be written to disk if as well if it is non-nil.
75
        InsertUnresolvedContracts(reports []*channeldb.ResolverReport,
76
                resolvers ...ContractResolver) error
77

78
        // FetchUnresolvedContracts returns all unresolved contracts that have
79
        // been previously written to the log.
80
        FetchUnresolvedContracts() ([]ContractResolver, error)
81

82
        // SwapContract performs an atomic swap of the old contract for the new
83
        // contract. This method is used when after a contract has been fully
84
        // resolved, it produces another contract that needs to be resolved.
85
        SwapContract(old ContractResolver, new ContractResolver) error
86

87
        // ResolveContract marks a contract as fully resolved. Once a contract
88
        // has been fully resolved, it is deleted from persistent storage.
89
        ResolveContract(ContractResolver) error
90

91
        // LogContractResolutions stores a complete contract resolution for the
92
        // contract under watch. This method will be called once the
93
        // ChannelArbitrator either force closes a channel, or detects that the
94
        // remote party has broadcast their commitment on chain.
95
        LogContractResolutions(*ContractResolutions) error
96

97
        // FetchContractResolutions fetches the set of previously stored
98
        // contract resolutions from persistent storage.
99
        FetchContractResolutions() (*ContractResolutions, error)
100

101
        // InsertConfirmedCommitSet stores the known set of active HTLCs at the
102
        // time channel closure. We'll use this to reconstruct our set of chain
103
        // actions anew based on the confirmed and pending commitment state.
104
        InsertConfirmedCommitSet(c *CommitSet) error
105

106
        // FetchConfirmedCommitSet fetches the known confirmed active HTLC set
107
        // from the database. It takes an optional database transaction, which
108
        // will be used if it is non-nil, otherwise the lookup will be done in
109
        // its own transaction.
110
        FetchConfirmedCommitSet(tx kvdb.RTx) (*CommitSet, error)
111

112
        // FetchChainActions attempts to fetch the set of previously stored
113
        // chain actions. We'll use this upon restart to properly advance our
114
        // state machine forward.
115
        //
116
        // NOTE: This method only exists in order to be able to serve nodes had
117
        // channels in the process of closing before the CommitSet struct was
118
        // introduced.
119
        FetchChainActions() (ChainActionMap, error)
120

121
        // WipeHistory is to be called ONLY once *all* contracts have been
122
        // fully resolved, and the channel closure if finalized. This method
123
        // will delete all on-disk state within the persistent log.
124
        WipeHistory() error
125
}
126

127
// ArbitratorState is an enum that details the current state of the
128
// ChannelArbitrator's state machine.
129
type ArbitratorState uint8
130

131
const (
132
        // While some state transition is allowed, certain transitions are not
133
        // possible. Listed below is the full state transition map which
134
        // contains all possible paths. We start at StateDefault and end at
135
        // StateFullyResolved, or StateError(not listed as its a possible state
136
        // in every path). The format is,
137
        //         -> state: conditions we switch to this state.
138
        //
139
        // StateDefault
140
        // |
141
        // |-> StateDefault: no actions and chain trigger
142
        // |
143
        // |-> StateBroadcastCommit: chain/user trigger
144
        // |   |
145
        // |   |-> StateCommitmentBroadcasted: chain/user trigger
146
        // |   |   |
147
        // |   |   |-> StateCommitmentBroadcasted: chain/user trigger
148
        // |   |   |
149
        // |   |   |-> StateContractClosed: local/remote/breach close trigger
150
        // |   |   |   |
151
        // |   |   |   |-> StateWaitingFullResolution: contract resolutions not empty
152
        // |   |   |   |   |
153
        // |   |   |   |   |-> StateWaitingFullResolution: contract resolutions not empty
154
        // |   |   |   |   |
155
        // |   |   |   |   |-> StateFullyResolved: contract resolutions empty
156
        // |   |   |   |
157
        // |   |   |   |-> StateFullyResolved: contract resolutions empty
158
        // |   |   |
159
        // |   |   |-> StateFullyResolved: coop/breach(legacy) close trigger
160
        // |   |
161
        // |   |-> StateContractClosed: local/remote/breach close trigger
162
        // |   |   |
163
        // |   |   |-> StateWaitingFullResolution: contract resolutions not empty
164
        // |   |   |   |
165
        // |   |   |   |-> StateWaitingFullResolution: contract resolutions not empty
166
        // |   |   |   |
167
        // |   |   |   |-> StateFullyResolved: contract resolutions empty
168
        // |   |   |
169
        // |   |   |-> StateFullyResolved: contract resolutions empty
170
        // |   |
171
        // |   |-> StateFullyResolved: coop/breach(legacy) close trigger
172
        // |
173
        // |-> StateContractClosed: local/remote/breach close trigger
174
        // |   |
175
        // |   |-> StateWaitingFullResolution: contract resolutions not empty
176
        // |   |   |
177
        // |   |   |-> StateWaitingFullResolution: contract resolutions not empty
178
        // |   |   |
179
        // |   |   |-> StateFullyResolved: contract resolutions empty
180
        // |   |
181
        // |   |-> StateFullyResolved: contract resolutions empty
182
        // |
183
        // |-> StateFullyResolved: coop/breach(legacy) close trigger.
184

185
        // StateDefault is the default state. In this state, no major actions
186
        // need to be executed.
187
        StateDefault ArbitratorState = 0
188

189
        // StateBroadcastCommit is a state that indicates that the attendant
190
        // has decided to broadcast the commitment transaction, but hasn't done
191
        // so yet.
192
        StateBroadcastCommit ArbitratorState = 1
193

194
        // StateCommitmentBroadcasted is a state that indicates that the
195
        // attendant has broadcasted the commitment transaction, and is now
196
        // waiting for it to confirm.
197
        StateCommitmentBroadcasted ArbitratorState = 6
198

199
        // StateContractClosed is a state that indicates the contract has
200
        // already been "closed", meaning the commitment is confirmed on chain.
201
        // At this point, we can now examine our active contracts, in order to
202
        // create the proper resolver for each one.
203
        StateContractClosed ArbitratorState = 2
204

205
        // StateWaitingFullResolution is a state that indicates that the
206
        // commitment transaction has been confirmed, and the attendant is now
207
        // waiting for all unresolved contracts to be fully resolved.
208
        StateWaitingFullResolution ArbitratorState = 3
209

210
        // StateFullyResolved is the final state of the attendant. In this
211
        // state, all related contracts have been resolved, and the attendant
212
        // can now be garbage collected.
213
        StateFullyResolved ArbitratorState = 4
214

215
        // StateError is the only error state of the resolver. If we enter this
216
        // state, then we cannot proceed with manual intervention as a state
217
        // transition failed.
218
        StateError ArbitratorState = 5
219
)
220

221
// String returns a human readable string describing the ArbitratorState.
222
func (a ArbitratorState) String() string {
3✔
223
        switch a {
3✔
224
        case StateDefault:
3✔
225
                return "StateDefault"
3✔
226

227
        case StateBroadcastCommit:
3✔
228
                return "StateBroadcastCommit"
3✔
229

230
        case StateCommitmentBroadcasted:
3✔
231
                return "StateCommitmentBroadcasted"
3✔
232

233
        case StateContractClosed:
3✔
234
                return "StateContractClosed"
3✔
235

236
        case StateWaitingFullResolution:
3✔
237
                return "StateWaitingFullResolution"
3✔
238

239
        case StateFullyResolved:
3✔
240
                return "StateFullyResolved"
3✔
241

242
        case StateError:
×
243
                return "StateError"
×
244

245
        default:
×
246
                return "unknown state"
×
247
        }
248
}
249

250
// resolverType is an enum that enumerates the various types of resolvers. When
251
// writing resolvers to disk, we prepend this to the raw bytes stored. This
252
// allows us to properly decode the resolver into the proper type.
253
type resolverType uint8
254

255
const (
256
        // resolverTimeout is the type of a resolver that's tasked with
257
        // resolving an outgoing HTLC that is very close to timing out.
258
        resolverTimeout resolverType = 0
259

260
        // resolverSuccess is the type of a resolver that's tasked with
261
        // resolving an incoming HTLC that we already know the preimage of.
262
        resolverSuccess resolverType = 1
263

264
        // resolverOutgoingContest is the type of a resolver that's tasked with
265
        // resolving an outgoing HTLC that hasn't yet timed out.
266
        resolverOutgoingContest resolverType = 2
267

268
        // resolverIncomingContest is the type of a resolver that's tasked with
269
        // resolving an incoming HTLC that we don't yet know the preimage to.
270
        resolverIncomingContest resolverType = 3
271

272
        // resolverUnilateralSweep is the type of resolver that's tasked with
273
        // sweeping out direct commitment output form the remote party's
274
        // commitment transaction.
275
        resolverUnilateralSweep resolverType = 4
276

277
        // resolverBreach is the type of resolver that manages a contract
278
        // breach on-chain.
279
        resolverBreach resolverType = 5
280
)
281

282
// resolverIDLen is the size of the resolver ID key. This is 36 bytes as we get
283
// 32 bytes from the hash of the prev tx, and 4 bytes for the output index.
284
const resolverIDLen = 36
285

286
// resolverID is a key that uniquely identifies a resolver within a particular
287
// chain. For this value we use the full outpoint of the resolver.
288
type resolverID [resolverIDLen]byte
289

290
// newResolverID returns a resolverID given the outpoint of a contract.
291
func newResolverID(op wire.OutPoint) resolverID {
3✔
292
        var r resolverID
3✔
293

3✔
294
        copy(r[:], op.Hash[:])
3✔
295

3✔
296
        endian.PutUint32(r[32:], op.Index)
3✔
297

3✔
298
        return r
3✔
299
}
3✔
300

301
// logScope is a key that we use to scope the storage of a ChannelArbitrator
302
// within the global log. We use this key to create a unique bucket within the
303
// database and ensure that we don't have any key collisions. The log's scope
304
// is define as: chainHash || chanPoint, where chanPoint is the chan point of
305
// the original channel.
306
type logScope [32 + 36]byte
307

308
// newLogScope creates a new logScope key from the passed chainhash and
309
// chanPoint.
310
func newLogScope(chain chainhash.Hash, op wire.OutPoint) (*logScope, error) {
3✔
311
        var l logScope
3✔
312
        b := bytes.NewBuffer(l[0:0])
3✔
313

3✔
314
        if _, err := b.Write(chain[:]); err != nil {
3✔
315
                return nil, err
×
316
        }
×
317
        if _, err := b.Write(op.Hash[:]); err != nil {
3✔
318
                return nil, err
×
319
        }
×
320

321
        if err := binary.Write(b, endian, op.Index); err != nil {
3✔
322
                return nil, err
×
323
        }
×
324

325
        return &l, nil
3✔
326
}
327

328
var (
329
        // stateKey is the key that we use to store the current state of the
330
        // arbitrator.
331
        stateKey = []byte("state")
332

333
        // contractsBucketKey is the bucket within the logScope that will store
334
        // all the active unresolved contracts.
335
        contractsBucketKey = []byte("contractkey")
336

337
        // resolutionsKey is the key under the logScope that we'll use to store
338
        // the full set of resolutions for a channel.
339
        resolutionsKey = []byte("resolutions")
340

341
        // resolutionsSignDetailsKey is the key under the logScope where we
342
        // will store input.SignDetails for each HTLC resolution. If this is
343
        // not found under the logScope, it means it was written before
344
        // SignDetails was introduced, and should be set nil for each HTLC
345
        // resolution.
346
        resolutionsSignDetailsKey = []byte("resolutions-sign-details")
347

348
        // anchorResolutionKey is the key under the logScope that we'll use to
349
        // store the anchor resolution, if any.
350
        anchorResolutionKey = []byte("anchor-resolution")
351

352
        // breachResolutionKey is the key under the logScope that we'll use to
353
        // store the breach resolution, if any. This is used rather than the
354
        // resolutionsKey.
355
        breachResolutionKey = []byte("breach-resolution")
356

357
        // actionsBucketKey is the key under the logScope that we'll use to
358
        // store all chain actions once they're determined.
359
        actionsBucketKey = []byte("chain-actions")
360

361
        // commitSetKey is the primary key under the logScope that we'll use to
362
        // store the confirmed active HTLC sets once we learn that a channel
363
        // has closed out on chain.
364
        commitSetKey = []byte("commit-set")
365

366
        // taprootDataKey is the key we'll use to store taproot specific data
367
        // for the set of channels we'll need to sweep/claim.
368
        taprootDataKey = []byte("taproot-data")
369
)
370

371
var (
372
        // errScopeBucketNoExist is returned when we can't find the proper
373
        // bucket for an arbitrator's scope.
374
        errScopeBucketNoExist = fmt.Errorf("scope bucket not found")
375

376
        // errNoContracts is returned when no contracts are found within the
377
        // log.
378
        errNoContracts = fmt.Errorf("no stored contracts")
379

380
        // errNoResolutions is returned when the log doesn't contain any active
381
        // chain resolutions.
382
        errNoResolutions = fmt.Errorf("no contract resolutions exist")
383

384
        // errNoActions is returned when the log doesn't contain any stored
385
        // chain actions.
386
        errNoActions = fmt.Errorf("no chain actions exist")
387

388
        // errNoCommitSet is return when the log doesn't contained a CommitSet.
389
        // This can happen if the channel hasn't closed yet, or a client is
390
        // running an older version that didn't yet write this state.
391
        errNoCommitSet = fmt.Errorf("no commit set exists")
392
)
393

394
// boltArbitratorLog is an implementation of the ArbitratorLog interface backed
395
// by a bolt DB instance.
396
type boltArbitratorLog struct {
397
        db kvdb.Backend
398

399
        cfg ChannelArbitratorConfig
400

401
        scopeKey logScope
402
}
403

404
// newBoltArbitratorLog returns a new instance of the boltArbitratorLog given
405
// an arbitrator config, and the items needed to create its log scope.
406
func newBoltArbitratorLog(db kvdb.Backend, cfg ChannelArbitratorConfig,
407
        chainHash chainhash.Hash, chanPoint wire.OutPoint) (*boltArbitratorLog, error) {
3✔
408

3✔
409
        scope, err := newLogScope(chainHash, chanPoint)
3✔
410
        if err != nil {
3✔
411
                return nil, err
×
412
        }
×
413

414
        return &boltArbitratorLog{
3✔
415
                db:       db,
3✔
416
                cfg:      cfg,
3✔
417
                scopeKey: *scope,
3✔
418
        }, nil
3✔
419
}
420

421
// A compile time check to ensure boltArbitratorLog meets the ArbitratorLog
422
// interface.
423
var _ ArbitratorLog = (*boltArbitratorLog)(nil)
424

425
func fetchContractReadBucket(tx kvdb.RTx, scopeKey []byte) (kvdb.RBucket, error) {
3✔
426
        scopeBucket := tx.ReadBucket(scopeKey)
3✔
427
        if scopeBucket == nil {
3✔
428
                return nil, errScopeBucketNoExist
×
429
        }
×
430

431
        contractBucket := scopeBucket.NestedReadBucket(contractsBucketKey)
3✔
432
        if contractBucket == nil {
3✔
433
                return nil, errNoContracts
×
434
        }
×
435

436
        return contractBucket, nil
3✔
437
}
438

439
func fetchContractWriteBucket(tx kvdb.RwTx, scopeKey []byte) (kvdb.RwBucket, error) {
3✔
440
        scopeBucket, err := tx.CreateTopLevelBucket(scopeKey)
3✔
441
        if err != nil {
3✔
442
                return nil, err
×
443
        }
×
444

445
        contractBucket, err := scopeBucket.CreateBucketIfNotExists(
3✔
446
                contractsBucketKey,
3✔
447
        )
3✔
448
        if err != nil {
3✔
449
                return nil, err
×
450
        }
×
451

452
        return contractBucket, nil
3✔
453
}
454

455
// writeResolver is a helper method that writes a contract resolver and stores
456
// it it within the passed contractBucket using its unique resolutionsKey key.
457
func (b *boltArbitratorLog) writeResolver(contractBucket kvdb.RwBucket,
458
        res ContractResolver) error {
3✔
459

3✔
460
        // Only persist resolvers that are stateful. Stateless resolvers don't
3✔
461
        // expose a resolver key.
3✔
462
        resKey := res.ResolverKey()
3✔
463
        if resKey == nil {
6✔
464
                return nil
3✔
465
        }
3✔
466

467
        // First, we'll write to the buffer the type of this resolver. Using
468
        // this byte, we can later properly deserialize the resolver properly.
469
        var (
3✔
470
                buf   bytes.Buffer
3✔
471
                rType resolverType
3✔
472
        )
3✔
473
        switch res.(type) {
3✔
474
        case *htlcTimeoutResolver:
3✔
475
                rType = resolverTimeout
3✔
476
        case *htlcSuccessResolver:
3✔
477
                rType = resolverSuccess
3✔
478
        case *htlcOutgoingContestResolver:
3✔
479
                rType = resolverOutgoingContest
3✔
480
        case *htlcIncomingContestResolver:
3✔
481
                rType = resolverIncomingContest
3✔
482
        case *commitSweepResolver:
3✔
483
                rType = resolverUnilateralSweep
3✔
484
        case *breachResolver:
3✔
485
                rType = resolverBreach
3✔
486
        }
487
        if _, err := buf.Write([]byte{byte(rType)}); err != nil {
3✔
488
                return err
×
489
        }
×
490

491
        // With the type of the resolver written, we can then write out the raw
492
        // bytes of the resolver itself.
493
        if err := res.Encode(&buf); err != nil {
3✔
494
                return err
×
495
        }
×
496

497
        return contractBucket.Put(resKey, buf.Bytes())
3✔
498
}
499

500
// CurrentState returns the current state of the ChannelArbitrator. It takes an
501
// optional database transaction, which will be used if it is non-nil, otherwise
502
// the lookup will be done in its own transaction.
503
//
504
// NOTE: Part of the ContractResolver interface.
505
func (b *boltArbitratorLog) CurrentState(tx kvdb.RTx) (ArbitratorState, error) {
3✔
506
        var (
3✔
507
                s   ArbitratorState
3✔
508
                err error
3✔
509
        )
3✔
510

3✔
511
        if tx != nil {
6✔
512
                s, err = b.currentState(tx)
3✔
513
        } else {
6✔
514
                err = kvdb.View(b.db, func(tx kvdb.RTx) error {
6✔
515
                        s, err = b.currentState(tx)
3✔
516
                        return err
3✔
517
                }, func() {
6✔
518
                        s = 0
3✔
519
                })
3✔
520
        }
521

522
        if err != nil && err != errScopeBucketNoExist {
3✔
523
                return s, err
×
524
        }
×
525

526
        return s, nil
3✔
527
}
528

529
func (b *boltArbitratorLog) currentState(tx kvdb.RTx) (ArbitratorState, error) {
3✔
530
        scopeBucket := tx.ReadBucket(b.scopeKey[:])
3✔
531
        if scopeBucket == nil {
6✔
532
                return 0, errScopeBucketNoExist
3✔
533
        }
3✔
534

535
        stateBytes := scopeBucket.Get(stateKey)
3✔
536
        if stateBytes == nil {
3✔
537
                return 0, nil
×
538
        }
×
539

540
        return ArbitratorState(stateBytes[0]), nil
3✔
541
}
542

543
// CommitState persists, the current state of the chain attendant.
544
//
545
// NOTE: Part of the ContractResolver interface.
546
func (b *boltArbitratorLog) CommitState(s ArbitratorState) error {
3✔
547
        return kvdb.Batch(b.db, func(tx kvdb.RwTx) error {
6✔
548
                scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:])
3✔
549
                if err != nil {
3✔
550
                        return err
×
551
                }
×
552

553
                return scopeBucket.Put(stateKey[:], []byte{uint8(s)})
3✔
554
        })
555
}
556

557
// FetchUnresolvedContracts returns all unresolved contracts that have been
558
// previously written to the log.
559
//
560
// NOTE: Part of the ContractResolver interface.
561
func (b *boltArbitratorLog) FetchUnresolvedContracts() ([]ContractResolver, error) {
3✔
562
        resolverCfg := ResolverConfig{
3✔
563
                ChannelArbitratorConfig: b.cfg,
3✔
564
                Checkpoint:              b.checkpointContract,
3✔
565
        }
3✔
566
        var contracts []ContractResolver
3✔
567
        err := kvdb.View(b.db, func(tx kvdb.RTx) error {
6✔
568
                contractBucket, err := fetchContractReadBucket(tx, b.scopeKey[:])
3✔
569
                if err != nil {
3✔
570
                        return err
×
571
                }
×
572

573
                return contractBucket.ForEach(func(resKey, resBytes []byte) error {
6✔
574
                        if len(resKey) != resolverIDLen {
3✔
575
                                return nil
×
576
                        }
×
577

578
                        var res ContractResolver
3✔
579

3✔
580
                        // We'll snip off the first byte of the raw resolver
3✔
581
                        // bytes in order to extract what type of resolver
3✔
582
                        // we're about to encode.
3✔
583
                        resType := resolverType(resBytes[0])
3✔
584

3✔
585
                        // Then we'll create a reader using the remaining
3✔
586
                        // bytes.
3✔
587
                        resReader := bytes.NewReader(resBytes[1:])
3✔
588

3✔
589
                        switch resType {
3✔
590
                        case resolverTimeout:
3✔
591
                                res, err = newTimeoutResolverFromReader(
3✔
592
                                        resReader, resolverCfg,
3✔
593
                                )
3✔
594

595
                        case resolverSuccess:
3✔
596
                                res, err = newSuccessResolverFromReader(
3✔
597
                                        resReader, resolverCfg,
3✔
598
                                )
3✔
599

600
                        case resolverOutgoingContest:
3✔
601
                                res, err = newOutgoingContestResolverFromReader(
3✔
602
                                        resReader, resolverCfg,
3✔
603
                                )
3✔
604

605
                        case resolverIncomingContest:
3✔
606
                                res, err = newIncomingContestResolverFromReader(
3✔
607
                                        resReader, resolverCfg,
3✔
608
                                )
3✔
609

610
                        case resolverUnilateralSweep:
3✔
611
                                res, err = newCommitSweepResolverFromReader(
3✔
612
                                        resReader, resolverCfg,
3✔
613
                                )
3✔
614

615
                        case resolverBreach:
3✔
616
                                res, err = newBreachResolverFromReader(
3✔
617
                                        resReader, resolverCfg,
3✔
618
                                )
3✔
619

620
                        default:
×
621
                                return fmt.Errorf("unknown resolver type: %v", resType)
×
622
                        }
623

624
                        if err != nil {
3✔
625
                                return err
×
626
                        }
×
627

628
                        contracts = append(contracts, res)
3✔
629
                        return nil
3✔
630
                })
631
        }, func() {
3✔
632
                contracts = nil
3✔
633
        })
3✔
634
        if err != nil && err != errScopeBucketNoExist && err != errNoContracts {
3✔
635
                return nil, err
×
636
        }
×
637

638
        return contracts, nil
3✔
639
}
640

641
// InsertUnresolvedContracts inserts a set of unresolved contracts into the
642
// log. The log will then persistently store each contract until they've been
643
// swapped out, or resolved.
644
//
645
// NOTE: Part of the ContractResolver interface.
646
func (b *boltArbitratorLog) InsertUnresolvedContracts(reports []*channeldb.ResolverReport,
647
        resolvers ...ContractResolver) error {
3✔
648

3✔
649
        return kvdb.Batch(b.db, func(tx kvdb.RwTx) error {
6✔
650
                contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:])
3✔
651
                if err != nil {
3✔
652
                        return err
×
653
                }
×
654

655
                for _, resolver := range resolvers {
6✔
656
                        err = b.writeResolver(contractBucket, resolver)
3✔
657
                        if err != nil {
3✔
658
                                return err
×
659
                        }
×
660
                }
661

662
                // Persist any reports that are present.
663
                for _, report := range reports {
6✔
664
                        err := b.cfg.PutResolverReport(tx, report)
3✔
665
                        if err != nil {
3✔
666
                                return err
×
667
                        }
×
668
                }
669

670
                return nil
3✔
671
        })
672
}
673

674
// SwapContract performs an atomic swap of the old contract for the new
675
// contract. This method is used when after a contract has been fully resolved,
676
// it produces another contract that needs to be resolved.
677
//
678
// NOTE: Part of the ContractResolver interface.
679
func (b *boltArbitratorLog) SwapContract(oldContract, newContract ContractResolver) error {
3✔
680
        return kvdb.Batch(b.db, func(tx kvdb.RwTx) error {
6✔
681
                contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:])
3✔
682
                if err != nil {
3✔
683
                        return err
×
684
                }
×
685

686
                oldContractkey := oldContract.ResolverKey()
3✔
687
                if err := contractBucket.Delete(oldContractkey); err != nil {
3✔
688
                        return err
×
689
                }
×
690

691
                return b.writeResolver(contractBucket, newContract)
3✔
692
        })
693
}
694

695
// ResolveContract marks a contract as fully resolved. Once a contract has been
696
// fully resolved, it is deleted from persistent storage.
697
//
698
// NOTE: Part of the ContractResolver interface.
699
func (b *boltArbitratorLog) ResolveContract(res ContractResolver) error {
3✔
700
        return kvdb.Batch(b.db, func(tx kvdb.RwTx) error {
6✔
701
                contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:])
3✔
702
                if err != nil {
3✔
703
                        return err
×
704
                }
×
705

706
                resKey := res.ResolverKey()
3✔
707
                return contractBucket.Delete(resKey)
3✔
708
        })
709
}
710

711
// LogContractResolutions stores a set of chain actions which are derived from
712
// our set of active contracts, and the on-chain state. We'll write this et of
713
// cations when: we decide to go on-chain to resolve a contract, or we detect
714
// that the remote party has gone on-chain.
715
//
716
// NOTE: Part of the ContractResolver interface.
717
func (b *boltArbitratorLog) LogContractResolutions(c *ContractResolutions) error {
3✔
718
        return kvdb.Batch(b.db, func(tx kvdb.RwTx) error {
6✔
719
                scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:])
3✔
720
                if err != nil {
3✔
721
                        return err
×
722
                }
×
723

724
                var b bytes.Buffer
3✔
725

3✔
726
                if _, err := b.Write(c.CommitHash[:]); err != nil {
3✔
727
                        return err
×
728
                }
×
729

730
                // First, we'll write out the commit output's resolution.
731
                if c.CommitResolution == nil {
6✔
732
                        if err := binary.Write(&b, endian, false); err != nil {
3✔
733
                                return err
×
734
                        }
×
735
                } else {
3✔
736
                        if err := binary.Write(&b, endian, true); err != nil {
3✔
737
                                return err
×
738
                        }
×
739
                        err = encodeCommitResolution(&b, c.CommitResolution)
3✔
740
                        if err != nil {
3✔
741
                                return err
×
742
                        }
×
743
                }
744

745
                // As we write the HTLC resolutions, we'll serialize the sign
746
                // details for each, to store under a new key.
747
                var signDetailsBuf bytes.Buffer
3✔
748

3✔
749
                // With the output for the commitment transaction written, we
3✔
750
                // can now write out the resolutions for the incoming and
3✔
751
                // outgoing HTLC's.
3✔
752
                numIncoming := uint32(len(c.HtlcResolutions.IncomingHTLCs))
3✔
753
                if err := binary.Write(&b, endian, numIncoming); err != nil {
3✔
754
                        return err
×
755
                }
×
756
                for _, htlc := range c.HtlcResolutions.IncomingHTLCs {
6✔
757
                        err := encodeIncomingResolution(&b, &htlc)
3✔
758
                        if err != nil {
3✔
759
                                return err
×
760
                        }
×
761

762
                        err = encodeSignDetails(&signDetailsBuf, htlc.SignDetails)
3✔
763
                        if err != nil {
3✔
764
                                return err
×
765
                        }
×
766
                }
767
                numOutgoing := uint32(len(c.HtlcResolutions.OutgoingHTLCs))
3✔
768
                if err := binary.Write(&b, endian, numOutgoing); err != nil {
3✔
769
                        return err
×
770
                }
×
771
                for _, htlc := range c.HtlcResolutions.OutgoingHTLCs {
6✔
772
                        err := encodeOutgoingResolution(&b, &htlc)
3✔
773
                        if err != nil {
3✔
774
                                return err
×
775
                        }
×
776

777
                        err = encodeSignDetails(&signDetailsBuf, htlc.SignDetails)
3✔
778
                        if err != nil {
3✔
779
                                return err
×
780
                        }
×
781
                }
782

783
                // Put the resolutions under the resolutionsKey.
784
                err = scopeBucket.Put(resolutionsKey, b.Bytes())
3✔
785
                if err != nil {
3✔
786
                        return err
×
787
                }
×
788

789
                // We'll put the serialized sign details under its own key to
790
                // stay backwards compatible.
791
                err = scopeBucket.Put(
3✔
792
                        resolutionsSignDetailsKey, signDetailsBuf.Bytes(),
3✔
793
                )
3✔
794
                if err != nil {
3✔
795
                        return err
×
796
                }
×
797

798
                // Write out the anchor resolution if present.
799
                if c.AnchorResolution != nil {
6✔
800
                        var b bytes.Buffer
3✔
801
                        err := encodeAnchorResolution(&b, c.AnchorResolution)
3✔
802
                        if err != nil {
3✔
803
                                return err
×
804
                        }
×
805

806
                        err = scopeBucket.Put(anchorResolutionKey, b.Bytes())
3✔
807
                        if err != nil {
3✔
808
                                return err
×
809
                        }
×
810
                }
811

812
                // Write out the breach resolution if present.
813
                if c.BreachResolution != nil {
6✔
814
                        var b bytes.Buffer
3✔
815
                        err := encodeBreachResolution(&b, c.BreachResolution)
3✔
816
                        if err != nil {
3✔
817
                                return err
×
818
                        }
×
819

820
                        err = scopeBucket.Put(breachResolutionKey, b.Bytes())
3✔
821
                        if err != nil {
3✔
822
                                return err
×
823
                        }
×
824
                }
825

826
                // If this isn't a taproot channel, then we can exit early here
827
                // as there's no extra data to write.
828
                switch {
3✔
829
                case c.AnchorResolution == nil:
3✔
830
                        return nil
3✔
831
                case !txscript.IsPayToTaproot(
832
                        c.AnchorResolution.AnchorSignDescriptor.Output.PkScript,
833
                ):
3✔
834
                        return nil
3✔
835
                }
836

837
                // With everything else encoded, we'll now populate the taproot
838
                // specific items we need to store for the musig2 channels.
839
                var tb bytes.Buffer
3✔
840
                err = encodeTaprootAuxData(&tb, c)
3✔
841
                if err != nil {
3✔
842
                        return err
×
843
                }
×
844

845
                return scopeBucket.Put(taprootDataKey, tb.Bytes())
3✔
846
        })
847
}
848

849
// FetchContractResolutions fetches the set of previously stored contract
850
// resolutions from persistent storage.
851
//
852
// NOTE: Part of the ContractResolver interface.
853
func (b *boltArbitratorLog) FetchContractResolutions() (*ContractResolutions, error) {
3✔
854
        var c *ContractResolutions
3✔
855
        err := kvdb.View(b.db, func(tx kvdb.RTx) error {
6✔
856
                scopeBucket := tx.ReadBucket(b.scopeKey[:])
3✔
857
                if scopeBucket == nil {
3✔
858
                        return errScopeBucketNoExist
×
859
                }
×
860

861
                resolutionBytes := scopeBucket.Get(resolutionsKey)
3✔
862
                if resolutionBytes == nil {
3✔
863
                        return errNoResolutions
×
864
                }
×
865

866
                resReader := bytes.NewReader(resolutionBytes)
3✔
867

3✔
868
                _, err := io.ReadFull(resReader, c.CommitHash[:])
3✔
869
                if err != nil {
3✔
870
                        return err
×
871
                }
×
872

873
                // First, we'll attempt to read out the commit resolution (if
874
                // it exists).
875
                var haveCommitRes bool
3✔
876
                err = binary.Read(resReader, endian, &haveCommitRes)
3✔
877
                if err != nil {
3✔
878
                        return err
×
879
                }
×
880
                if haveCommitRes {
6✔
881
                        c.CommitResolution = &lnwallet.CommitOutputResolution{}
3✔
882
                        err = decodeCommitResolution(
3✔
883
                                resReader, c.CommitResolution,
3✔
884
                        )
3✔
885
                        if err != nil {
3✔
886
                                return fmt.Errorf("unable to decode "+
×
887
                                        "commit res: %w", err)
×
888
                        }
×
889
                }
890

891
                var (
3✔
892
                        numIncoming uint32
3✔
893
                        numOutgoing uint32
3✔
894
                )
3✔
895

3✔
896
                // Next, we'll read out the incoming and outgoing HTLC
3✔
897
                // resolutions.
3✔
898
                err = binary.Read(resReader, endian, &numIncoming)
3✔
899
                if err != nil {
3✔
900
                        return err
×
901
                }
×
902
                c.HtlcResolutions.IncomingHTLCs = make([]lnwallet.IncomingHtlcResolution, numIncoming)
3✔
903
                for i := uint32(0); i < numIncoming; i++ {
6✔
904
                        err := decodeIncomingResolution(
3✔
905
                                resReader, &c.HtlcResolutions.IncomingHTLCs[i],
3✔
906
                        )
3✔
907
                        if err != nil {
3✔
908
                                return fmt.Errorf("unable to decode "+
×
909
                                        "incoming res: %w", err)
×
910
                        }
×
911
                }
912

913
                err = binary.Read(resReader, endian, &numOutgoing)
3✔
914
                if err != nil {
3✔
915
                        return err
×
916
                }
×
917
                c.HtlcResolutions.OutgoingHTLCs = make([]lnwallet.OutgoingHtlcResolution, numOutgoing)
3✔
918
                for i := uint32(0); i < numOutgoing; i++ {
6✔
919
                        err := decodeOutgoingResolution(
3✔
920
                                resReader, &c.HtlcResolutions.OutgoingHTLCs[i],
3✔
921
                        )
3✔
922
                        if err != nil {
3✔
923
                                return fmt.Errorf("unable to decode "+
×
924
                                        "outgoing res: %w", err)
×
925
                        }
×
926
                }
927

928
                // Now we attempt to get the sign details for our HTLC
929
                // resolutions. If not present the channel is of a type that
930
                // doesn't need them. If present there will be SignDetails
931
                // encoded for each HTLC resolution.
932
                signDetailsBytes := scopeBucket.Get(resolutionsSignDetailsKey)
3✔
933
                if signDetailsBytes != nil {
6✔
934
                        r := bytes.NewReader(signDetailsBytes)
3✔
935

3✔
936
                        // They will be encoded in the same order as the
3✔
937
                        // resolutions: firs incoming HTLCs, then outgoing.
3✔
938
                        for i := uint32(0); i < numIncoming; i++ {
6✔
939
                                htlc := &c.HtlcResolutions.IncomingHTLCs[i]
3✔
940
                                htlc.SignDetails, err = decodeSignDetails(r)
3✔
941
                                if err != nil {
3✔
942
                                        return fmt.Errorf("unable to decode "+
×
943
                                                "incoming sign desc: %w", err)
×
944
                                }
×
945
                        }
946

947
                        for i := uint32(0); i < numOutgoing; i++ {
6✔
948
                                htlc := &c.HtlcResolutions.OutgoingHTLCs[i]
3✔
949
                                htlc.SignDetails, err = decodeSignDetails(r)
3✔
950
                                if err != nil {
3✔
951
                                        return fmt.Errorf("unable to decode "+
×
952
                                                "outgoing sign desc: %w", err)
×
953
                                }
×
954
                        }
955
                }
956

957
                anchorResBytes := scopeBucket.Get(anchorResolutionKey)
3✔
958
                if anchorResBytes != nil {
6✔
959
                        c.AnchorResolution = &lnwallet.AnchorResolution{}
3✔
960
                        resReader := bytes.NewReader(anchorResBytes)
3✔
961
                        err := decodeAnchorResolution(
3✔
962
                                resReader, c.AnchorResolution,
3✔
963
                        )
3✔
964
                        if err != nil {
3✔
965
                                return fmt.Errorf("unable to read anchor "+
×
966
                                        "data: %w", err)
×
967
                        }
×
968
                }
969

970
                breachResBytes := scopeBucket.Get(breachResolutionKey)
3✔
971
                if breachResBytes != nil {
6✔
972
                        c.BreachResolution = &BreachResolution{}
3✔
973
                        resReader := bytes.NewReader(breachResBytes)
3✔
974
                        err := decodeBreachResolution(
3✔
975
                                resReader, c.BreachResolution,
3✔
976
                        )
3✔
977
                        if err != nil {
3✔
978
                                return fmt.Errorf("unable to read breach "+
×
979
                                        "data: %w", err)
×
980
                        }
×
981
                }
982

983
                tapCaseBytes := scopeBucket.Get(taprootDataKey)
3✔
984
                if tapCaseBytes != nil {
6✔
985
                        err = decodeTapRootAuxData(
3✔
986
                                bytes.NewReader(tapCaseBytes), c,
3✔
987
                        )
3✔
988
                        if err != nil {
3✔
989
                                return fmt.Errorf("unable to read taproot "+
×
990
                                        "data: %w", err)
×
991
                        }
×
992
                }
993
                return nil
3✔
994
        }, func() {
3✔
995
                c = &ContractResolutions{}
3✔
996
        })
3✔
997
        if err != nil {
3✔
998
                return nil, err
×
999
        }
×
1000

1001
        return c, err
3✔
1002
}
1003

1004
// FetchChainActions attempts to fetch the set of previously stored chain
1005
// actions. We'll use this upon restart to properly advance our state machine
1006
// forward.
1007
//
1008
// NOTE: Part of the ContractResolver interface.
1009
func (b *boltArbitratorLog) FetchChainActions() (ChainActionMap, error) {
×
1010
        var actionsMap ChainActionMap
×
1011

×
1012
        err := kvdb.View(b.db, func(tx kvdb.RTx) error {
×
1013
                scopeBucket := tx.ReadBucket(b.scopeKey[:])
×
1014
                if scopeBucket == nil {
×
1015
                        return errScopeBucketNoExist
×
1016
                }
×
1017

1018
                actionsBucket := scopeBucket.NestedReadBucket(actionsBucketKey)
×
1019
                if actionsBucket == nil {
×
1020
                        return errNoActions
×
1021
                }
×
1022

1023
                return actionsBucket.ForEach(func(action, htlcBytes []byte) error {
×
1024
                        if htlcBytes == nil {
×
1025
                                return nil
×
1026
                        }
×
1027

1028
                        chainAction := ChainAction(action[0])
×
1029

×
1030
                        htlcReader := bytes.NewReader(htlcBytes)
×
1031
                        htlcs, err := channeldb.DeserializeHtlcs(htlcReader)
×
1032
                        if err != nil {
×
1033
                                return err
×
1034
                        }
×
1035

1036
                        actionsMap[chainAction] = htlcs
×
1037

×
1038
                        return nil
×
1039
                })
1040
        }, func() {
×
1041
                actionsMap = make(ChainActionMap)
×
1042
        })
×
1043
        if err != nil {
×
1044
                return nil, err
×
1045
        }
×
1046

1047
        return actionsMap, nil
×
1048
}
1049

1050
// InsertConfirmedCommitSet stores the known set of active HTLCs at the time
1051
// channel closure. We'll use this to reconstruct our set of chain actions anew
1052
// based on the confirmed and pending commitment state.
1053
//
1054
// NOTE: Part of the ContractResolver interface.
1055
func (b *boltArbitratorLog) InsertConfirmedCommitSet(c *CommitSet) error {
3✔
1056
        return kvdb.Batch(b.db, func(tx kvdb.RwTx) error {
6✔
1057
                scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:])
3✔
1058
                if err != nil {
3✔
1059
                        return err
×
1060
                }
×
1061

1062
                var b bytes.Buffer
3✔
1063
                if err := encodeCommitSet(&b, c); err != nil {
3✔
1064
                        return err
×
1065
                }
×
1066

1067
                return scopeBucket.Put(commitSetKey, b.Bytes())
3✔
1068
        })
1069
}
1070

1071
// FetchConfirmedCommitSet fetches the known confirmed active HTLC set from the
1072
// database. It takes an optional database transaction, which will be used if it
1073
// is non-nil, otherwise the lookup will be done in its own transaction.
1074
//
1075
// NOTE: Part of the ContractResolver interface.
1076
func (b *boltArbitratorLog) FetchConfirmedCommitSet(tx kvdb.RTx) (*CommitSet, error) {
3✔
1077
        if tx != nil {
6✔
1078
                return b.fetchConfirmedCommitSet(tx)
3✔
1079
        }
3✔
1080

1081
        var c *CommitSet
3✔
1082
        err := kvdb.View(b.db, func(tx kvdb.RTx) error {
6✔
1083
                var err error
3✔
1084
                c, err = b.fetchConfirmedCommitSet(tx)
3✔
1085
                return err
3✔
1086
        }, func() {
6✔
1087
                c = nil
3✔
1088
        })
3✔
1089
        if err != nil {
6✔
1090
                return nil, err
3✔
1091
        }
3✔
1092

1093
        return c, nil
×
1094
}
1095

1096
func (b *boltArbitratorLog) fetchConfirmedCommitSet(tx kvdb.RTx) (*CommitSet,
1097
        error) {
3✔
1098

3✔
1099
        scopeBucket := tx.ReadBucket(b.scopeKey[:])
3✔
1100
        if scopeBucket == nil {
6✔
1101
                return nil, errScopeBucketNoExist
3✔
1102
        }
3✔
1103

1104
        commitSetBytes := scopeBucket.Get(commitSetKey)
3✔
1105
        if commitSetBytes == nil {
6✔
1106
                return nil, errNoCommitSet
3✔
1107
        }
3✔
1108

1109
        return decodeCommitSet(bytes.NewReader(commitSetBytes))
3✔
1110
}
1111

1112
// WipeHistory is to be called ONLY once *all* contracts have been fully
1113
// resolved, and the channel closure if finalized. This method will delete all
1114
// on-disk state within the persistent log.
1115
//
1116
// NOTE: Part of the ContractResolver interface.
1117
func (b *boltArbitratorLog) WipeHistory() error {
3✔
1118
        return kvdb.Update(b.db, func(tx kvdb.RwTx) error {
6✔
1119
                scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:])
3✔
1120
                if err != nil {
3✔
1121
                        return err
×
1122
                }
×
1123

1124
                // Once we have the main top-level bucket, we'll delete the key
1125
                // that stores the state of the arbitrator.
1126
                if err := scopeBucket.Delete(stateKey[:]); err != nil {
3✔
1127
                        return err
×
1128
                }
×
1129

1130
                // Next, we'll delete any lingering contract state within the
1131
                // contracts bucket by removing the bucket itself.
1132
                err = scopeBucket.DeleteNestedBucket(contractsBucketKey)
3✔
1133
                if err != nil && err != kvdb.ErrBucketNotFound {
3✔
1134
                        return err
×
1135
                }
×
1136

1137
                // Next, we'll delete storage of any lingering contract
1138
                // resolutions.
1139
                if err := scopeBucket.Delete(resolutionsKey); err != nil {
3✔
1140
                        return err
×
1141
                }
×
1142

1143
                err = scopeBucket.Delete(resolutionsSignDetailsKey)
3✔
1144
                if err != nil {
3✔
1145
                        return err
×
1146
                }
×
1147

1148
                // We'll delete any chain actions that are still stored by
1149
                // removing the enclosing bucket.
1150
                err = scopeBucket.DeleteNestedBucket(actionsBucketKey)
3✔
1151
                if err != nil && err != kvdb.ErrBucketNotFound {
3✔
1152
                        return err
×
1153
                }
×
1154

1155
                // Finally, we'll delete the enclosing bucket itself.
1156
                return tx.DeleteTopLevelBucket(b.scopeKey[:])
3✔
1157
        }, func() {})
3✔
1158
}
1159

1160
// checkpointContract is a private method that will be fed into
1161
// ContractResolver instances to checkpoint their state once they reach
1162
// milestones during contract resolution. If the report provided is non-nil,
1163
// it should also be recorded.
1164
func (b *boltArbitratorLog) checkpointContract(c ContractResolver,
1165
        reports ...*channeldb.ResolverReport) error {
3✔
1166

3✔
1167
        return kvdb.Update(b.db, func(tx kvdb.RwTx) error {
6✔
1168
                contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:])
3✔
1169
                if err != nil {
3✔
1170
                        return err
×
1171
                }
×
1172

1173
                if err := b.writeResolver(contractBucket, c); err != nil {
3✔
1174
                        return err
×
1175
                }
×
1176

1177
                for _, report := range reports {
6✔
1178
                        if err := b.cfg.PutResolverReport(tx, report); err != nil {
3✔
1179
                                return err
×
1180
                        }
×
1181
                }
1182

1183
                return nil
3✔
1184
        }, func() {})
3✔
1185
}
1186

1187
// encodeSignDetails encodes the given SignDetails struct to the writer.
1188
// SignDetails is allowed to be nil, in which we will encode that it is not
1189
// present.
1190
func encodeSignDetails(w io.Writer, s *input.SignDetails) error {
3✔
1191
        // If we don't have sign details, write false and return.
3✔
1192
        if s == nil {
6✔
1193
                return binary.Write(w, endian, false)
3✔
1194
        }
3✔
1195

1196
        // Otherwise write true, and the contents of the SignDetails.
1197
        if err := binary.Write(w, endian, true); err != nil {
3✔
1198
                return err
×
1199
        }
×
1200

1201
        err := input.WriteSignDescriptor(w, &s.SignDesc)
3✔
1202
        if err != nil {
3✔
1203
                return err
×
1204
        }
×
1205
        err = binary.Write(w, endian, uint32(s.SigHashType))
3✔
1206
        if err != nil {
3✔
1207
                return err
×
1208
        }
×
1209

1210
        // Write the DER-encoded signature.
1211
        b := s.PeerSig.Serialize()
3✔
1212
        if err := wire.WriteVarBytes(w, 0, b); err != nil {
3✔
1213
                return err
×
1214
        }
×
1215

1216
        return nil
3✔
1217
}
1218

1219
// decodeSignDetails extracts a single SignDetails from the reader. It is
1220
// allowed to return nil in case the SignDetails were empty.
1221
func decodeSignDetails(r io.Reader) (*input.SignDetails, error) {
3✔
1222
        var present bool
3✔
1223
        if err := binary.Read(r, endian, &present); err != nil {
3✔
1224
                return nil, err
×
1225
        }
×
1226

1227
        // Simply return nil if the next SignDetails was not present.
1228
        if !present {
6✔
1229
                return nil, nil
3✔
1230
        }
3✔
1231

1232
        // Otherwise decode the elements of the SignDetails.
1233
        s := input.SignDetails{}
3✔
1234
        err := input.ReadSignDescriptor(r, &s.SignDesc)
3✔
1235
        if err != nil {
3✔
1236
                return nil, err
×
1237
        }
×
1238

1239
        var sigHash uint32
3✔
1240
        err = binary.Read(r, endian, &sigHash)
3✔
1241
        if err != nil {
3✔
1242
                return nil, err
×
1243
        }
×
1244
        s.SigHashType = txscript.SigHashType(sigHash)
3✔
1245

3✔
1246
        // Read DER-encoded signature.
3✔
1247
        rawSig, err := wire.ReadVarBytes(r, 0, 200, "signature")
3✔
1248
        if err != nil {
3✔
1249
                return nil, err
×
1250
        }
×
1251

1252
        s.PeerSig, err = input.ParseSignature(rawSig)
3✔
1253
        if err != nil {
3✔
1254
                return nil, err
×
1255
        }
×
1256

1257
        return &s, nil
3✔
1258
}
1259

1260
func encodeIncomingResolution(w io.Writer, i *lnwallet.IncomingHtlcResolution) error {
3✔
1261
        if _, err := w.Write(i.Preimage[:]); err != nil {
3✔
1262
                return err
×
1263
        }
×
1264

1265
        if i.SignedSuccessTx == nil {
6✔
1266
                if err := binary.Write(w, endian, false); err != nil {
3✔
1267
                        return err
×
1268
                }
×
1269
        } else {
3✔
1270
                if err := binary.Write(w, endian, true); err != nil {
3✔
1271
                        return err
×
1272
                }
×
1273

1274
                if err := i.SignedSuccessTx.Serialize(w); err != nil {
3✔
1275
                        return err
×
1276
                }
×
1277
        }
1278

1279
        if err := binary.Write(w, endian, i.CsvDelay); err != nil {
3✔
1280
                return err
×
1281
        }
×
1282
        if _, err := w.Write(i.ClaimOutpoint.Hash[:]); err != nil {
3✔
1283
                return err
×
1284
        }
×
1285
        if err := binary.Write(w, endian, i.ClaimOutpoint.Index); err != nil {
3✔
1286
                return err
×
1287
        }
×
1288
        err := input.WriteSignDescriptor(w, &i.SweepSignDesc)
3✔
1289
        if err != nil {
3✔
1290
                return err
×
1291
        }
×
1292

1293
        return nil
3✔
1294
}
1295

1296
func decodeIncomingResolution(r io.Reader, h *lnwallet.IncomingHtlcResolution) error {
3✔
1297
        if _, err := io.ReadFull(r, h.Preimage[:]); err != nil {
3✔
1298
                return err
×
1299
        }
×
1300

1301
        var txPresent bool
3✔
1302
        if err := binary.Read(r, endian, &txPresent); err != nil {
3✔
1303
                return err
×
1304
        }
×
1305
        if txPresent {
6✔
1306
                h.SignedSuccessTx = &wire.MsgTx{}
3✔
1307
                if err := h.SignedSuccessTx.Deserialize(r); err != nil {
3✔
1308
                        return err
×
1309
                }
×
1310
        }
1311

1312
        err := binary.Read(r, endian, &h.CsvDelay)
3✔
1313
        if err != nil {
3✔
1314
                return err
×
1315
        }
×
1316
        _, err = io.ReadFull(r, h.ClaimOutpoint.Hash[:])
3✔
1317
        if err != nil {
3✔
1318
                return err
×
1319
        }
×
1320
        err = binary.Read(r, endian, &h.ClaimOutpoint.Index)
3✔
1321
        if err != nil {
3✔
1322
                return err
×
1323
        }
×
1324

1325
        return input.ReadSignDescriptor(r, &h.SweepSignDesc)
3✔
1326
}
1327

1328
func encodeOutgoingResolution(w io.Writer, o *lnwallet.OutgoingHtlcResolution) error {
3✔
1329
        if err := binary.Write(w, endian, o.Expiry); err != nil {
3✔
1330
                return err
×
1331
        }
×
1332

1333
        if o.SignedTimeoutTx == nil {
6✔
1334
                if err := binary.Write(w, endian, false); err != nil {
3✔
1335
                        return err
×
1336
                }
×
1337
        } else {
3✔
1338
                if err := binary.Write(w, endian, true); err != nil {
3✔
1339
                        return err
×
1340
                }
×
1341

1342
                if err := o.SignedTimeoutTx.Serialize(w); err != nil {
3✔
1343
                        return err
×
1344
                }
×
1345
        }
1346

1347
        if err := binary.Write(w, endian, o.CsvDelay); err != nil {
3✔
1348
                return err
×
1349
        }
×
1350
        if _, err := w.Write(o.ClaimOutpoint.Hash[:]); err != nil {
3✔
1351
                return err
×
1352
        }
×
1353
        if err := binary.Write(w, endian, o.ClaimOutpoint.Index); err != nil {
3✔
1354
                return err
×
1355
        }
×
1356

1357
        return input.WriteSignDescriptor(w, &o.SweepSignDesc)
3✔
1358
}
1359

1360
func decodeOutgoingResolution(r io.Reader, o *lnwallet.OutgoingHtlcResolution) error {
3✔
1361
        err := binary.Read(r, endian, &o.Expiry)
3✔
1362
        if err != nil {
3✔
1363
                return err
×
1364
        }
×
1365

1366
        var txPresent bool
3✔
1367
        if err := binary.Read(r, endian, &txPresent); err != nil {
3✔
1368
                return err
×
1369
        }
×
1370
        if txPresent {
6✔
1371
                o.SignedTimeoutTx = &wire.MsgTx{}
3✔
1372
                if err := o.SignedTimeoutTx.Deserialize(r); err != nil {
3✔
1373
                        return err
×
1374
                }
×
1375
        }
1376

1377
        err = binary.Read(r, endian, &o.CsvDelay)
3✔
1378
        if err != nil {
3✔
1379
                return err
×
1380
        }
×
1381
        _, err = io.ReadFull(r, o.ClaimOutpoint.Hash[:])
3✔
1382
        if err != nil {
3✔
1383
                return err
×
1384
        }
×
1385
        err = binary.Read(r, endian, &o.ClaimOutpoint.Index)
3✔
1386
        if err != nil {
3✔
1387
                return err
×
1388
        }
×
1389

1390
        return input.ReadSignDescriptor(r, &o.SweepSignDesc)
3✔
1391
}
1392

1393
func encodeCommitResolution(w io.Writer,
1394
        c *lnwallet.CommitOutputResolution) error {
3✔
1395

3✔
1396
        if _, err := w.Write(c.SelfOutPoint.Hash[:]); err != nil {
3✔
1397
                return err
×
1398
        }
×
1399
        err := binary.Write(w, endian, c.SelfOutPoint.Index)
3✔
1400
        if err != nil {
3✔
1401
                return err
×
1402
        }
×
1403

1404
        err = input.WriteSignDescriptor(w, &c.SelfOutputSignDesc)
3✔
1405
        if err != nil {
3✔
1406
                return err
×
1407
        }
×
1408

1409
        return binary.Write(w, endian, c.MaturityDelay)
3✔
1410
}
1411

1412
func decodeCommitResolution(r io.Reader,
1413
        c *lnwallet.CommitOutputResolution) error {
3✔
1414

3✔
1415
        _, err := io.ReadFull(r, c.SelfOutPoint.Hash[:])
3✔
1416
        if err != nil {
3✔
1417
                return err
×
1418
        }
×
1419
        err = binary.Read(r, endian, &c.SelfOutPoint.Index)
3✔
1420
        if err != nil {
3✔
1421
                return err
×
1422
        }
×
1423

1424
        err = input.ReadSignDescriptor(r, &c.SelfOutputSignDesc)
3✔
1425
        if err != nil {
3✔
1426
                return err
×
1427
        }
×
1428

1429
        return binary.Read(r, endian, &c.MaturityDelay)
3✔
1430
}
1431

1432
func encodeAnchorResolution(w io.Writer,
1433
        a *lnwallet.AnchorResolution) error {
3✔
1434

3✔
1435
        if _, err := w.Write(a.CommitAnchor.Hash[:]); err != nil {
3✔
1436
                return err
×
1437
        }
×
1438
        err := binary.Write(w, endian, a.CommitAnchor.Index)
3✔
1439
        if err != nil {
3✔
1440
                return err
×
1441
        }
×
1442

1443
        return input.WriteSignDescriptor(w, &a.AnchorSignDescriptor)
3✔
1444
}
1445

1446
func decodeAnchorResolution(r io.Reader,
1447
        a *lnwallet.AnchorResolution) error {
3✔
1448

3✔
1449
        _, err := io.ReadFull(r, a.CommitAnchor.Hash[:])
3✔
1450
        if err != nil {
3✔
1451
                return err
×
1452
        }
×
1453
        err = binary.Read(r, endian, &a.CommitAnchor.Index)
3✔
1454
        if err != nil {
3✔
1455
                return err
×
1456
        }
×
1457

1458
        return input.ReadSignDescriptor(r, &a.AnchorSignDescriptor)
3✔
1459
}
1460

1461
func encodeBreachResolution(w io.Writer, b *BreachResolution) error {
3✔
1462
        if _, err := w.Write(b.FundingOutPoint.Hash[:]); err != nil {
3✔
1463
                return err
×
1464
        }
×
1465
        return binary.Write(w, endian, b.FundingOutPoint.Index)
3✔
1466
}
1467

1468
func decodeBreachResolution(r io.Reader, b *BreachResolution) error {
3✔
1469
        _, err := io.ReadFull(r, b.FundingOutPoint.Hash[:])
3✔
1470
        if err != nil {
3✔
1471
                return err
×
1472
        }
×
1473
        return binary.Read(r, endian, &b.FundingOutPoint.Index)
3✔
1474
}
1475

1476
func encodeHtlcSetKey(w io.Writer, h *HtlcSetKey) error {
3✔
1477
        err := binary.Write(w, endian, h.IsRemote)
3✔
1478
        if err != nil {
3✔
1479
                return err
×
1480
        }
×
1481
        return binary.Write(w, endian, h.IsPending)
3✔
1482
}
1483

1484
func encodeCommitSet(w io.Writer, c *CommitSet) error {
3✔
1485
        if err := encodeHtlcSetKey(w, c.ConfCommitKey); err != nil {
3✔
1486
                return err
×
1487
        }
×
1488

1489
        numSets := uint8(len(c.HtlcSets))
3✔
1490
        if err := binary.Write(w, endian, numSets); err != nil {
3✔
1491
                return err
×
1492
        }
×
1493

1494
        for htlcSetKey, htlcs := range c.HtlcSets {
6✔
1495
                htlcSetKey := htlcSetKey
3✔
1496
                if err := encodeHtlcSetKey(w, &htlcSetKey); err != nil {
3✔
1497
                        return err
×
1498
                }
×
1499

1500
                if err := channeldb.SerializeHtlcs(w, htlcs...); err != nil {
3✔
1501
                        return err
×
1502
                }
×
1503
        }
1504

1505
        return nil
3✔
1506
}
1507

1508
func decodeHtlcSetKey(r io.Reader, h *HtlcSetKey) error {
3✔
1509
        err := binary.Read(r, endian, &h.IsRemote)
3✔
1510
        if err != nil {
3✔
1511
                return err
×
1512
        }
×
1513

1514
        return binary.Read(r, endian, &h.IsPending)
3✔
1515
}
1516

1517
func decodeCommitSet(r io.Reader) (*CommitSet, error) {
3✔
1518
        c := &CommitSet{
3✔
1519
                ConfCommitKey: &HtlcSetKey{},
3✔
1520
                HtlcSets:      make(map[HtlcSetKey][]channeldb.HTLC),
3✔
1521
        }
3✔
1522

3✔
1523
        if err := decodeHtlcSetKey(r, c.ConfCommitKey); err != nil {
3✔
1524
                return nil, err
×
1525
        }
×
1526

1527
        var numSets uint8
3✔
1528
        if err := binary.Read(r, endian, &numSets); err != nil {
3✔
1529
                return nil, err
×
1530
        }
×
1531

1532
        for i := uint8(0); i < numSets; i++ {
6✔
1533
                var htlcSetKey HtlcSetKey
3✔
1534
                if err := decodeHtlcSetKey(r, &htlcSetKey); err != nil {
3✔
1535
                        return nil, err
×
1536
                }
×
1537

1538
                htlcs, err := channeldb.DeserializeHtlcs(r)
3✔
1539
                if err != nil {
3✔
1540
                        return nil, err
×
1541
                }
×
1542

1543
                c.HtlcSets[htlcSetKey] = htlcs
3✔
1544
        }
1545

1546
        return c, nil
3✔
1547
}
1548

1549
func encodeTaprootAuxData(w io.Writer, c *ContractResolutions) error {
3✔
1550
        tapCase := newTaprootBriefcase()
3✔
1551

3✔
1552
        if c.CommitResolution != nil {
6✔
1553
                commitResolution := c.CommitResolution
3✔
1554
                commitSignDesc := commitResolution.SelfOutputSignDesc
3✔
1555
                //nolint:lll
3✔
1556
                tapCase.CtrlBlocks.CommitSweepCtrlBlock = commitSignDesc.ControlBlock
3✔
1557
        }
3✔
1558

1559
        for _, htlc := range c.HtlcResolutions.IncomingHTLCs {
6✔
1560
                htlc := htlc
3✔
1561

3✔
1562
                htlcSignDesc := htlc.SweepSignDesc
3✔
1563
                ctrlBlock := htlcSignDesc.ControlBlock
3✔
1564

3✔
1565
                if ctrlBlock == nil {
3✔
1566
                        continue
×
1567
                }
1568

1569
                if htlc.SignedSuccessTx != nil {
6✔
1570
                        resID := newResolverID(
3✔
1571
                                htlc.SignedSuccessTx.TxIn[0].PreviousOutPoint,
3✔
1572
                        )
3✔
1573
                        //nolint:lll
3✔
1574
                        tapCase.CtrlBlocks.SecondLevelCtrlBlocks[resID] = ctrlBlock
3✔
1575

3✔
1576
                        // For HTLCs we need to go to the second level for, we
3✔
1577
                        // also need to store the control block needed to
3✔
1578
                        // publish the second level transaction.
3✔
1579
                        if htlc.SignDetails != nil {
6✔
1580
                                //nolint:lll
3✔
1581
                                bridgeCtrlBlock := htlc.SignDetails.SignDesc.ControlBlock
3✔
1582
                                //nolint:lll
3✔
1583
                                tapCase.CtrlBlocks.IncomingHtlcCtrlBlocks[resID] = bridgeCtrlBlock
3✔
1584
                        }
3✔
1585
                } else {
3✔
1586
                        resID := newResolverID(htlc.ClaimOutpoint)
3✔
1587
                        //nolint:lll
3✔
1588
                        tapCase.CtrlBlocks.IncomingHtlcCtrlBlocks[resID] = ctrlBlock
3✔
1589
                }
3✔
1590
        }
1591
        for _, htlc := range c.HtlcResolutions.OutgoingHTLCs {
6✔
1592
                htlc := htlc
3✔
1593

3✔
1594
                htlcSignDesc := htlc.SweepSignDesc
3✔
1595
                ctrlBlock := htlcSignDesc.ControlBlock
3✔
1596

3✔
1597
                if ctrlBlock == nil {
3✔
1598
                        continue
×
1599
                }
1600

1601
                if htlc.SignedTimeoutTx != nil {
6✔
1602
                        resID := newResolverID(
3✔
1603
                                htlc.SignedTimeoutTx.TxIn[0].PreviousOutPoint,
3✔
1604
                        )
3✔
1605
                        //nolint:lll
3✔
1606
                        tapCase.CtrlBlocks.SecondLevelCtrlBlocks[resID] = ctrlBlock
3✔
1607

3✔
1608
                        // For HTLCs we need to go to the second level for, we
3✔
1609
                        // also need to store the control block needed to
3✔
1610
                        // publish the second level transaction.
3✔
1611
                        //
3✔
1612
                        //nolint:lll
3✔
1613
                        if htlc.SignDetails != nil {
6✔
1614
                                //nolint:lll
3✔
1615
                                bridgeCtrlBlock := htlc.SignDetails.SignDesc.ControlBlock
3✔
1616
                                //nolint:lll
3✔
1617
                                tapCase.CtrlBlocks.OutgoingHtlcCtrlBlocks[resID] = bridgeCtrlBlock
3✔
1618
                        }
3✔
1619
                } else {
3✔
1620
                        resID := newResolverID(htlc.ClaimOutpoint)
3✔
1621
                        //nolint:lll
3✔
1622
                        tapCase.CtrlBlocks.OutgoingHtlcCtrlBlocks[resID] = ctrlBlock
3✔
1623
                }
3✔
1624
        }
1625

1626
        if c.AnchorResolution != nil {
6✔
1627
                anchorSignDesc := c.AnchorResolution.AnchorSignDescriptor
3✔
1628
                tapCase.TapTweaks.AnchorTweak = anchorSignDesc.TapTweak
3✔
1629
        }
3✔
1630

1631
        return tapCase.Encode(w)
3✔
1632
}
1633

1634
func decodeTapRootAuxData(r io.Reader, c *ContractResolutions) error {
3✔
1635
        tapCase := newTaprootBriefcase()
3✔
1636
        if err := tapCase.Decode(r); err != nil {
3✔
1637
                return err
×
1638
        }
×
1639

1640
        if c.CommitResolution != nil {
6✔
1641
                c.CommitResolution.SelfOutputSignDesc.ControlBlock =
3✔
1642
                        tapCase.CtrlBlocks.CommitSweepCtrlBlock
3✔
1643
        }
3✔
1644

1645
        for i := range c.HtlcResolutions.IncomingHTLCs {
6✔
1646
                htlc := c.HtlcResolutions.IncomingHTLCs[i]
3✔
1647

3✔
1648
                var resID resolverID
3✔
1649
                if htlc.SignedSuccessTx != nil {
6✔
1650
                        resID = newResolverID(
3✔
1651
                                htlc.SignedSuccessTx.TxIn[0].PreviousOutPoint,
3✔
1652
                        )
3✔
1653

3✔
1654
                        //nolint:lll
3✔
1655
                        ctrlBlock := tapCase.CtrlBlocks.SecondLevelCtrlBlocks[resID]
3✔
1656
                        htlc.SweepSignDesc.ControlBlock = ctrlBlock
3✔
1657

3✔
1658
                        //nolint:lll
3✔
1659
                        if htlc.SignDetails != nil {
6✔
1660
                                bridgeCtrlBlock := tapCase.CtrlBlocks.IncomingHtlcCtrlBlocks[resID]
3✔
1661
                                htlc.SignDetails.SignDesc.ControlBlock = bridgeCtrlBlock
3✔
1662
                        }
3✔
1663
                } else {
3✔
1664
                        resID = newResolverID(htlc.ClaimOutpoint)
3✔
1665

3✔
1666
                        //nolint:lll
3✔
1667
                        ctrlBlock := tapCase.CtrlBlocks.IncomingHtlcCtrlBlocks[resID]
3✔
1668
                        htlc.SweepSignDesc.ControlBlock = ctrlBlock
3✔
1669
                }
3✔
1670

1671
                c.HtlcResolutions.IncomingHTLCs[i] = htlc
3✔
1672
        }
1673
        for i := range c.HtlcResolutions.OutgoingHTLCs {
6✔
1674
                htlc := c.HtlcResolutions.OutgoingHTLCs[i]
3✔
1675

3✔
1676
                var resID resolverID
3✔
1677
                if htlc.SignedTimeoutTx != nil {
6✔
1678
                        resID = newResolverID(
3✔
1679
                                htlc.SignedTimeoutTx.TxIn[0].PreviousOutPoint,
3✔
1680
                        )
3✔
1681

3✔
1682
                        //nolint:lll
3✔
1683
                        ctrlBlock := tapCase.CtrlBlocks.SecondLevelCtrlBlocks[resID]
3✔
1684
                        htlc.SweepSignDesc.ControlBlock = ctrlBlock
3✔
1685

3✔
1686
                        //nolint:lll
3✔
1687
                        if htlc.SignDetails != nil {
6✔
1688
                                bridgeCtrlBlock := tapCase.CtrlBlocks.OutgoingHtlcCtrlBlocks[resID]
3✔
1689
                                htlc.SignDetails.SignDesc.ControlBlock = bridgeCtrlBlock
3✔
1690
                        }
3✔
1691
                } else {
3✔
1692
                        resID = newResolverID(htlc.ClaimOutpoint)
3✔
1693

3✔
1694
                        //nolint:lll
3✔
1695
                        ctrlBlock := tapCase.CtrlBlocks.OutgoingHtlcCtrlBlocks[resID]
3✔
1696
                        htlc.SweepSignDesc.ControlBlock = ctrlBlock
3✔
1697
                }
3✔
1698

1699
                c.HtlcResolutions.OutgoingHTLCs[i] = htlc
3✔
1700
        }
1701

1702
        if c.AnchorResolution != nil {
6✔
1703
                c.AnchorResolution.AnchorSignDescriptor.TapTweak =
3✔
1704
                        tapCase.TapTweaks.AnchorTweak
3✔
1705
        }
3✔
1706

1707
        return nil
3✔
1708
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc