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

lightningnetwork / lnd / 12312390362

13 Dec 2024 08:44AM UTC coverage: 57.458% (+8.5%) from 48.92%
12312390362

Pull #9343

github

ellemouton
fn: rework the ContextGuard and add tests

In this commit, the ContextGuard struct is re-worked such that the
context that its new main WithCtx method provides is cancelled in sync
with a parent context being cancelled or with it's quit channel being
cancelled. Tests are added to assert the behaviour. In order for the
close of the quit channel to be consistent with the cancelling of the
derived context, the quit channel _must_ be contained internal to the
ContextGuard so that callers are only able to close the channel via the
exposed Quit method which will then take care to first cancel any
derived context that depend on the quit channel before returning.
Pull Request #9343: fn: expand the ContextGuard and add tests

101853 of 177264 relevant lines covered (57.46%)

24972.93 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