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

lightningnetwork / lnd / 12284350326

11 Dec 2024 08:27PM UTC coverage: 57.485% (+7.9%) from 49.54%
12284350326

Pull #9348

github

ziggie1984
github: update goveralls tool
Pull Request #9348: github: update goveralls tool

101901 of 177264 relevant lines covered (57.49%)

24841.21 hits per line

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

50.73
/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/fn/v2"
14
        "github.com/lightningnetwork/lnd/input"
15
        "github.com/lightningnetwork/lnd/kvdb"
16
        "github.com/lightningnetwork/lnd/lnwallet"
17
        "github.com/lightningnetwork/lnd/tlv"
18
)
19

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

229
        case StateBroadcastCommit:
×
230
                return "StateBroadcastCommit"
×
231

232
        case StateCommitmentBroadcasted:
×
233
                return "StateCommitmentBroadcasted"
×
234

235
        case StateContractClosed:
2✔
236
                return "StateContractClosed"
2✔
237

238
        case StateWaitingFullResolution:
×
239
                return "StateWaitingFullResolution"
×
240

241
        case StateFullyResolved:
1✔
242
                return "StateFullyResolved"
1✔
243

244
        case StateError:
×
245
                return "StateError"
×
246

247
        default:
×
248
                return "unknown state"
×
249
        }
250
}
251

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

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

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

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

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

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

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

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

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

292
// newResolverID returns a resolverID given the outpoint of a contract.
293
func newResolverID(op wire.OutPoint) resolverID {
32✔
294
        var r resolverID
32✔
295

32✔
296
        copy(r[:], op.Hash[:])
32✔
297

32✔
298
        endian.PutUint32(r[32:], op.Index)
32✔
299

32✔
300
        return r
32✔
301
}
32✔
302

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

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

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

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

327
        return &l, nil
20✔
328
}
329

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

401
        cfg ChannelArbitratorConfig
402

403
        scopeKey logScope
404
}
405

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

20✔
411
        scope, err := newLogScope(chainHash, chanPoint)
20✔
412
        if err != nil {
20✔
413
                return nil, err
×
414
        }
×
415

416
        return &boltArbitratorLog{
20✔
417
                db:       db,
20✔
418
                cfg:      cfg,
20✔
419
                scopeKey: *scope,
20✔
420
        }, nil
20✔
421
}
422

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

427
func fetchContractReadBucket(tx kvdb.RTx, scopeKey []byte) (kvdb.RBucket, error) {
9✔
428
        scopeBucket := tx.ReadBucket(scopeKey)
9✔
429
        if scopeBucket == nil {
10✔
430
                return nil, errScopeBucketNoExist
1✔
431
        }
1✔
432

433
        contractBucket := scopeBucket.NestedReadBucket(contractsBucketKey)
8✔
434
        if contractBucket == nil {
8✔
435
                return nil, errNoContracts
×
436
        }
×
437

438
        return contractBucket, nil
8✔
439
}
440

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

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

454
        return contractBucket, nil
10✔
455
}
456

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

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

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

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

499
        return contractBucket.Put(resKey, buf.Bytes())
12✔
500
}
501

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

18✔
513
        if tx != nil {
29✔
514
                s, err = b.currentState(tx)
11✔
515
        } else {
18✔
516
                err = kvdb.View(b.db, func(tx kvdb.RTx) error {
14✔
517
                        s, err = b.currentState(tx)
7✔
518
                        return err
7✔
519
                }, func() {
14✔
520
                        s = 0
7✔
521
                })
7✔
522
        }
523

524
        if err != nil && err != errScopeBucketNoExist {
18✔
525
                return s, err
×
526
        }
×
527

528
        return s, nil
18✔
529
}
530

531
func (b *boltArbitratorLog) currentState(tx kvdb.RTx) (ArbitratorState, error) {
18✔
532
        scopeBucket := tx.ReadBucket(b.scopeKey[:])
18✔
533
        if scopeBucket == nil {
32✔
534
                return 0, errScopeBucketNoExist
14✔
535
        }
14✔
536

537
        stateBytes := scopeBucket.Get(stateKey)
4✔
538
        if stateBytes == nil {
4✔
539
                return 0, nil
×
540
        }
×
541

542
        return ArbitratorState(stateBytes[0]), nil
4✔
543
}
544

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

555
                return scopeBucket.Put(stateKey[:], []byte{uint8(s)})
8✔
556
        })
557
}
558

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

575
                return contractBucket.ForEach(func(resKey, resBytes []byte) error {
18✔
576
                        if len(resKey) != resolverIDLen {
10✔
577
                                return nil
×
578
                        }
×
579

580
                        var res ContractResolver
10✔
581

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

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

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

597
                        case resolverSuccess:
1✔
598
                                res, err = newSuccessResolverFromReader(
1✔
599
                                        resReader, resolverCfg,
1✔
600
                                )
1✔
601

602
                        case resolverOutgoingContest:
4✔
603
                                res, err = newOutgoingContestResolverFromReader(
4✔
604
                                        resReader, resolverCfg,
4✔
605
                                )
4✔
606

607
                        case resolverIncomingContest:
1✔
608
                                res, err = newIncomingContestResolverFromReader(
1✔
609
                                        resReader, resolverCfg,
1✔
610
                                )
1✔
611

612
                        case resolverUnilateralSweep:
1✔
613
                                res, err = newCommitSweepResolverFromReader(
1✔
614
                                        resReader, resolverCfg,
1✔
615
                                )
1✔
616

617
                        case resolverBreach:
×
618
                                res, err = newBreachResolverFromReader(
×
619
                                        resReader, resolverCfg,
×
620
                                )
×
621

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

626
                        if err != nil {
10✔
627
                                return err
×
628
                        }
×
629

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

640
        return contracts, nil
9✔
641
}
642

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

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

657
                for _, resolver := range resolvers {
12✔
658
                        err = b.writeResolver(contractBucket, resolver)
8✔
659
                        if err != nil {
8✔
660
                                return err
×
661
                        }
×
662
                }
663

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

672
                return nil
4✔
673
        })
674
}
675

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

688
                oldContractkey := oldContract.ResolverKey()
2✔
689
                if err := contractBucket.Delete(oldContractkey); err != nil {
2✔
690
                        return err
×
691
                }
×
692

693
                return b.writeResolver(contractBucket, newContract)
2✔
694
        })
695
}
696

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

708
                resKey := res.ResolverKey()
2✔
709
                return contractBucket.Delete(resKey)
2✔
710
        })
711
}
712

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

726
                var b bytes.Buffer
2✔
727

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

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

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

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

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

779
                        err = encodeSignDetails(&signDetailsBuf, htlc.SignDetails)
4✔
780
                        if err != nil {
4✔
781
                                return err
×
782
                        }
×
783
                }
784

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

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

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

808
                        err = scopeBucket.Put(anchorResolutionKey, b.Bytes())
1✔
809
                        if err != nil {
1✔
810
                                return err
×
811
                        }
×
812
                }
813

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

822
                        err = scopeBucket.Put(breachResolutionKey, b.Bytes())
×
823
                        if err != nil {
×
824
                                return err
×
825
                        }
×
826
                }
827

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

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

847
                return scopeBucket.Put(taprootDataKey, tb.Bytes())
×
848
        })
849
}
850

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

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

868
                resReader := bytes.NewReader(resolutionBytes)
3✔
869

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

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

893
                var (
3✔
894
                        numIncoming uint32
3✔
895
                        numOutgoing uint32
3✔
896
                )
3✔
897

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

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

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

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

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

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

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

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

1003
        return c, err
3✔
1004
}
1005

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

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

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

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

1030
                        chainAction := ChainAction(action[0])
×
1031

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

1038
                        actionsMap[chainAction] = htlcs
×
1039

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

1049
        return actionsMap, nil
×
1050
}
1051

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

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

1069
                return scopeBucket.Put(commitSetKey, b.Bytes())
7✔
1070
        })
1071
}
1072

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

1083
        var c *CommitSet
8✔
1084
        err := kvdb.View(b.db, func(tx kvdb.RTx) error {
16✔
1085
                var err error
8✔
1086
                c, err = b.fetchConfirmedCommitSet(tx)
8✔
1087
                return err
8✔
1088
        }, func() {
16✔
1089
                c = nil
8✔
1090
        })
8✔
1091
        if err != nil {
9✔
1092
                return nil, err
1✔
1093
        }
1✔
1094

1095
        return c, nil
7✔
1096
}
1097

1098
func (b *boltArbitratorLog) fetchConfirmedCommitSet(tx kvdb.RTx) (*CommitSet,
1099
        error) {
19✔
1100

19✔
1101
        scopeBucket := tx.ReadBucket(b.scopeKey[:])
19✔
1102
        if scopeBucket == nil {
31✔
1103
                return nil, errScopeBucketNoExist
12✔
1104
        }
12✔
1105

1106
        commitSetBytes := scopeBucket.Get(commitSetKey)
7✔
1107
        if commitSetBytes == nil {
7✔
1108
                return nil, errNoCommitSet
×
1109
        }
×
1110

1111
        return decodeCommitSet(bytes.NewReader(commitSetBytes))
7✔
1112
}
1113

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

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

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

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

1145
                err = scopeBucket.Delete(resolutionsSignDetailsKey)
4✔
1146
                if err != nil {
4✔
1147
                        return err
×
1148
                }
×
1149

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

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

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

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

1175
                if err := b.writeResolver(contractBucket, c); err != nil {
2✔
1176
                        return err
×
1177
                }
×
1178

1179
                for _, report := range reports {
4✔
1180
                        if err := b.cfg.PutResolverReport(tx, report); err != nil {
2✔
1181
                                return err
×
1182
                        }
×
1183
                }
1184

1185
                return nil
2✔
1186
        }, func() {})
2✔
1187
}
1188

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

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

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

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

1218
        return nil
11✔
1219
}
1220

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

1229
        // Simply return nil if the next SignDetails was not present.
1230
        if !present {
56✔
1231
                return nil, nil
24✔
1232
        }
24✔
1233

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

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

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

1254
        s.PeerSig, err = input.ParseSignature(rawSig)
8✔
1255
        if err != nil {
8✔
1256
                return nil, err
×
1257
        }
×
1258

1259
        return &s, nil
8✔
1260
}
1261

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

1267
        if i.SignedSuccessTx == nil {
16✔
1268
                if err := binary.Write(w, endian, false); err != nil {
4✔
1269
                        return err
×
1270
                }
×
1271
        } else {
8✔
1272
                if err := binary.Write(w, endian, true); err != nil {
8✔
1273
                        return err
×
1274
                }
×
1275

1276
                if err := i.SignedSuccessTx.Serialize(w); err != nil {
8✔
1277
                        return err
×
1278
                }
×
1279
        }
1280

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

1295
        return nil
12✔
1296
}
1297

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

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

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

1327
        return input.ReadSignDescriptor(r, &h.SweepSignDesc)
10✔
1328
}
1329

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

1335
        if o.SignedTimeoutTx == nil {
35✔
1336
                if err := binary.Write(w, endian, false); err != nil {
8✔
1337
                        return err
×
1338
                }
×
1339
        } else {
19✔
1340
                if err := binary.Write(w, endian, true); err != nil {
19✔
1341
                        return err
×
1342
                }
×
1343

1344
                if err := o.SignedTimeoutTx.Serialize(w); err != nil {
19✔
1345
                        return err
×
1346
                }
×
1347
        }
1348

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

1359
        return input.WriteSignDescriptor(w, &o.SweepSignDesc)
27✔
1360
}
1361

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

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

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

1392
        return input.ReadSignDescriptor(r, &o.SweepSignDesc)
22✔
1393
}
1394

1395
func encodeCommitResolution(w io.Writer,
1396
        c *lnwallet.CommitOutputResolution) error {
2✔
1397

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

1406
        err = input.WriteSignDescriptor(w, &c.SelfOutputSignDesc)
2✔
1407
        if err != nil {
2✔
1408
                return err
×
1409
        }
×
1410

1411
        return binary.Write(w, endian, c.MaturityDelay)
2✔
1412
}
1413

1414
func decodeCommitResolution(r io.Reader,
1415
        c *lnwallet.CommitOutputResolution) error {
2✔
1416

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

1426
        err = input.ReadSignDescriptor(r, &c.SelfOutputSignDesc)
2✔
1427
        if err != nil {
2✔
1428
                return err
×
1429
        }
×
1430

1431
        return binary.Read(r, endian, &c.MaturityDelay)
2✔
1432
}
1433

1434
func encodeAnchorResolution(w io.Writer,
1435
        a *lnwallet.AnchorResolution) error {
1✔
1436

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

1445
        return input.WriteSignDescriptor(w, &a.AnchorSignDescriptor)
1✔
1446
}
1447

1448
func decodeAnchorResolution(r io.Reader,
1449
        a *lnwallet.AnchorResolution) error {
1✔
1450

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

1460
        return input.ReadSignDescriptor(r, &a.AnchorSignDescriptor)
1✔
1461
}
1462

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

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

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

1484
        return binary.Write(w, endian, htlcSetKey.IsPending)
23✔
1485
}
1486

1487
func encodeCommitSet(w io.Writer, c *CommitSet) error {
7✔
1488
        confCommitKey, err := c.ConfCommitKey.UnwrapOrErr(
7✔
1489
                fmt.Errorf("HtlcSetKey is not set"),
7✔
1490
        )
7✔
1491
        if err != nil {
7✔
1492
                return err
×
1493
        }
×
1494
        if err := encodeHtlcSetKey(w, confCommitKey); err != nil {
7✔
1495
                return err
×
1496
        }
×
1497

1498
        numSets := uint8(len(c.HtlcSets))
7✔
1499
        if err := binary.Write(w, endian, numSets); err != nil {
7✔
1500
                return err
×
1501
        }
×
1502

1503
        for htlcSetKey, htlcs := range c.HtlcSets {
23✔
1504
                if err := encodeHtlcSetKey(w, htlcSetKey); err != nil {
16✔
1505
                        return err
×
1506
                }
×
1507

1508
                if err := channeldb.SerializeHtlcs(w, htlcs...); err != nil {
16✔
1509
                        return err
×
1510
                }
×
1511
        }
1512

1513
        return nil
7✔
1514
}
1515

1516
func decodeHtlcSetKey(r io.Reader, h *HtlcSetKey) error {
23✔
1517
        err := binary.Read(r, endian, &h.IsRemote)
23✔
1518
        if err != nil {
23✔
1519
                return err
×
1520
        }
×
1521

1522
        return binary.Read(r, endian, &h.IsPending)
23✔
1523
}
1524

1525
func decodeCommitSet(r io.Reader) (*CommitSet, error) {
7✔
1526
        confCommitKey := HtlcSetKey{}
7✔
1527
        if err := decodeHtlcSetKey(r, &confCommitKey); err != nil {
7✔
1528
                return nil, err
×
1529
        }
×
1530

1531
        c := &CommitSet{
7✔
1532
                ConfCommitKey: fn.Some(confCommitKey),
7✔
1533
                HtlcSets:      make(map[HtlcSetKey][]channeldb.HTLC),
7✔
1534
        }
7✔
1535

7✔
1536
        var numSets uint8
7✔
1537
        if err := binary.Read(r, endian, &numSets); err != nil {
7✔
1538
                return nil, err
×
1539
        }
×
1540

1541
        for i := uint8(0); i < numSets; i++ {
23✔
1542
                var htlcSetKey HtlcSetKey
16✔
1543
                if err := decodeHtlcSetKey(r, &htlcSetKey); err != nil {
16✔
1544
                        return nil, err
×
1545
                }
×
1546

1547
                htlcs, err := channeldb.DeserializeHtlcs(r)
16✔
1548
                if err != nil {
16✔
1549
                        return nil, err
×
1550
                }
×
1551

1552
                c.HtlcSets[htlcSetKey] = htlcs
16✔
1553
        }
1554

1555
        return c, nil
7✔
1556
}
1557

1558
func encodeTaprootAuxData(w io.Writer, c *ContractResolutions) error {
×
1559
        tapCase := newTaprootBriefcase()
×
1560

×
1561
        if c.CommitResolution != nil {
×
1562
                commitResolution := c.CommitResolution
×
1563
                commitSignDesc := commitResolution.SelfOutputSignDesc
×
1564
                //nolint:ll
×
1565
                tapCase.CtrlBlocks.Val.CommitSweepCtrlBlock = commitSignDesc.ControlBlock
×
1566

×
1567
                c.CommitResolution.ResolutionBlob.WhenSome(func(b []byte) {
×
1568
                        tapCase.SettledCommitBlob = tlv.SomeRecordT(
×
1569
                                tlv.NewPrimitiveRecord[tlv.TlvType2](b),
×
1570
                        )
×
1571
                })
×
1572
        }
1573

1574
        htlcBlobs := newAuxHtlcBlobs()
×
1575
        for _, htlc := range c.HtlcResolutions.IncomingHTLCs {
×
1576
                htlc := htlc
×
1577

×
1578
                htlcSignDesc := htlc.SweepSignDesc
×
1579
                ctrlBlock := htlcSignDesc.ControlBlock
×
1580

×
1581
                if ctrlBlock == nil {
×
1582
                        continue
×
1583
                }
1584

1585
                var resID resolverID
×
1586
                if htlc.SignedSuccessTx != nil {
×
1587
                        resID = newResolverID(
×
1588
                                htlc.SignedSuccessTx.TxIn[0].PreviousOutPoint,
×
1589
                        )
×
1590
                        //nolint:ll
×
1591
                        tapCase.CtrlBlocks.Val.SecondLevelCtrlBlocks[resID] = ctrlBlock
×
1592

×
1593
                        // For HTLCs we need to go to the second level for, we
×
1594
                        // also need to store the control block needed to
×
1595
                        // publish the second level transaction.
×
1596
                        if htlc.SignDetails != nil {
×
1597
                                //nolint:ll
×
1598
                                bridgeCtrlBlock := htlc.SignDetails.SignDesc.ControlBlock
×
1599
                                //nolint:ll
×
1600
                                tapCase.CtrlBlocks.Val.IncomingHtlcCtrlBlocks[resID] = bridgeCtrlBlock
×
1601
                        }
×
1602
                } else {
×
1603
                        resID = newResolverID(htlc.ClaimOutpoint)
×
1604
                        //nolint:ll
×
1605
                        tapCase.CtrlBlocks.Val.IncomingHtlcCtrlBlocks[resID] = ctrlBlock
×
1606
                }
×
1607

1608
                htlc.ResolutionBlob.WhenSome(func(b []byte) {
×
1609
                        htlcBlobs[resID] = b
×
1610
                })
×
1611
        }
1612
        for _, htlc := range c.HtlcResolutions.OutgoingHTLCs {
×
1613
                htlc := htlc
×
1614

×
1615
                htlcSignDesc := htlc.SweepSignDesc
×
1616
                ctrlBlock := htlcSignDesc.ControlBlock
×
1617

×
1618
                if ctrlBlock == nil {
×
1619
                        continue
×
1620
                }
1621

1622
                var resID resolverID
×
1623
                if htlc.SignedTimeoutTx != nil {
×
1624
                        resID = newResolverID(
×
1625
                                htlc.SignedTimeoutTx.TxIn[0].PreviousOutPoint,
×
1626
                        )
×
1627
                        //nolint:ll
×
1628
                        tapCase.CtrlBlocks.Val.SecondLevelCtrlBlocks[resID] = ctrlBlock
×
1629

×
1630
                        // For HTLCs we need to go to the second level for, we
×
1631
                        // also need to store the control block needed to
×
1632
                        // publish the second level transaction.
×
1633
                        //
×
1634
                        //nolint:ll
×
1635
                        if htlc.SignDetails != nil {
×
1636
                                //nolint:ll
×
1637
                                bridgeCtrlBlock := htlc.SignDetails.SignDesc.ControlBlock
×
1638
                                //nolint:ll
×
1639
                                tapCase.CtrlBlocks.Val.OutgoingHtlcCtrlBlocks[resID] = bridgeCtrlBlock
×
1640
                        }
×
1641
                } else {
×
1642
                        resID = newResolverID(htlc.ClaimOutpoint)
×
1643
                        //nolint:ll
×
1644
                        tapCase.CtrlBlocks.Val.OutgoingHtlcCtrlBlocks[resID] = ctrlBlock
×
1645
                }
×
1646

1647
                htlc.ResolutionBlob.WhenSome(func(b []byte) {
×
1648
                        htlcBlobs[resID] = b
×
1649
                })
×
1650
        }
1651

1652
        if c.AnchorResolution != nil {
×
1653
                anchorSignDesc := c.AnchorResolution.AnchorSignDescriptor
×
1654
                tapCase.TapTweaks.Val.AnchorTweak = anchorSignDesc.TapTweak
×
1655
        }
×
1656

1657
        if len(htlcBlobs) != 0 {
×
1658
                tapCase.HtlcBlobs = tlv.SomeRecordT(
×
1659
                        tlv.NewRecordT[tlv.TlvType4](htlcBlobs),
×
1660
                )
×
1661
        }
×
1662

1663
        return tapCase.Encode(w)
×
1664
}
1665

1666
func decodeTapRootAuxData(r io.Reader, c *ContractResolutions) error {
×
1667
        tapCase := newTaprootBriefcase()
×
1668
        if err := tapCase.Decode(r); err != nil {
×
1669
                return err
×
1670
        }
×
1671

1672
        if c.CommitResolution != nil {
×
1673
                c.CommitResolution.SelfOutputSignDesc.ControlBlock =
×
1674
                        tapCase.CtrlBlocks.Val.CommitSweepCtrlBlock
×
1675

×
1676
                tapCase.SettledCommitBlob.WhenSomeV(func(b []byte) {
×
1677
                        c.CommitResolution.ResolutionBlob = fn.Some(b)
×
1678
                })
×
1679
        }
1680

1681
        htlcBlobs := tapCase.HtlcBlobs.ValOpt().UnwrapOr(newAuxHtlcBlobs())
×
1682

×
1683
        for i := range c.HtlcResolutions.IncomingHTLCs {
×
1684
                htlc := c.HtlcResolutions.IncomingHTLCs[i]
×
1685

×
1686
                var resID resolverID
×
1687
                if htlc.SignedSuccessTx != nil {
×
1688
                        resID = newResolverID(
×
1689
                                htlc.SignedSuccessTx.TxIn[0].PreviousOutPoint,
×
1690
                        )
×
1691

×
1692
                        //nolint:ll
×
1693
                        ctrlBlock := tapCase.CtrlBlocks.Val.SecondLevelCtrlBlocks[resID]
×
1694
                        htlc.SweepSignDesc.ControlBlock = ctrlBlock
×
1695

×
1696
                        //nolint:ll
×
1697
                        if htlc.SignDetails != nil {
×
1698
                                bridgeCtrlBlock := tapCase.CtrlBlocks.Val.IncomingHtlcCtrlBlocks[resID]
×
1699
                                htlc.SignDetails.SignDesc.ControlBlock = bridgeCtrlBlock
×
1700
                        }
×
1701
                } else {
×
1702
                        resID = newResolverID(htlc.ClaimOutpoint)
×
1703

×
1704
                        //nolint:ll
×
1705
                        ctrlBlock := tapCase.CtrlBlocks.Val.IncomingHtlcCtrlBlocks[resID]
×
1706
                        htlc.SweepSignDesc.ControlBlock = ctrlBlock
×
1707
                }
×
1708

1709
                if htlcBlob, ok := htlcBlobs[resID]; ok {
×
1710
                        htlc.ResolutionBlob = fn.Some(htlcBlob)
×
1711
                }
×
1712

1713
                c.HtlcResolutions.IncomingHTLCs[i] = htlc
×
1714

1715
        }
1716
        for i := range c.HtlcResolutions.OutgoingHTLCs {
×
1717
                htlc := c.HtlcResolutions.OutgoingHTLCs[i]
×
1718

×
1719
                var resID resolverID
×
1720
                if htlc.SignedTimeoutTx != nil {
×
1721
                        resID = newResolverID(
×
1722
                                htlc.SignedTimeoutTx.TxIn[0].PreviousOutPoint,
×
1723
                        )
×
1724

×
1725
                        //nolint:ll
×
1726
                        ctrlBlock := tapCase.CtrlBlocks.Val.SecondLevelCtrlBlocks[resID]
×
1727
                        htlc.SweepSignDesc.ControlBlock = ctrlBlock
×
1728

×
1729
                        //nolint:ll
×
1730
                        if htlc.SignDetails != nil {
×
1731
                                bridgeCtrlBlock := tapCase.CtrlBlocks.Val.OutgoingHtlcCtrlBlocks[resID]
×
1732
                                htlc.SignDetails.SignDesc.ControlBlock = bridgeCtrlBlock
×
1733
                        }
×
1734
                } else {
×
1735
                        resID = newResolverID(htlc.ClaimOutpoint)
×
1736

×
1737
                        //nolint:ll
×
1738
                        ctrlBlock := tapCase.CtrlBlocks.Val.OutgoingHtlcCtrlBlocks[resID]
×
1739
                        htlc.SweepSignDesc.ControlBlock = ctrlBlock
×
1740
                }
×
1741

1742
                if htlcBlob, ok := htlcBlobs[resID]; ok {
×
1743
                        htlc.ResolutionBlob = fn.Some(htlcBlob)
×
1744
                }
×
1745

1746
                c.HtlcResolutions.OutgoingHTLCs[i] = htlc
×
1747
        }
1748

1749
        if c.AnchorResolution != nil {
×
1750
                c.AnchorResolution.AnchorSignDescriptor.TapTweak =
×
1751
                        tapCase.TapTweaks.Val.AnchorTweak
×
1752
        }
×
1753

1754
        return nil
×
1755
}
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