github.com/decred/dcrlnd@v0.7.6/contractcourt/briefcase.go (about) 1 package contractcourt 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "io" 8 9 "github.com/decred/dcrd/chaincfg/chainhash" 10 "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" 11 "github.com/decred/dcrd/txscript/v4" 12 "github.com/decred/dcrd/wire" 13 "github.com/decred/dcrlnd/channeldb" 14 "github.com/decred/dcrlnd/input" 15 "github.com/decred/dcrlnd/kvdb" 16 "github.com/decred/dcrlnd/lnwallet" 17 ) 18 19 // ContractResolutions is a wrapper struct around the two forms of resolutions 20 // we may need to carry out once a contract is closing: resolving the 21 // commitment output, and resolving any incoming+outgoing HTLC's still present 22 // in the commitment. 23 type ContractResolutions struct { 24 // CommitHash is the txid of the commitment transaction. 25 CommitHash chainhash.Hash 26 27 // CommitResolution contains all data required to fully resolve a 28 // commitment output. 29 CommitResolution *lnwallet.CommitOutputResolution 30 31 // HtlcResolutions contains all data required to fully resolve any 32 // incoming+outgoing HTLC's present within the commitment transaction. 33 HtlcResolutions lnwallet.HtlcResolutions 34 35 // AnchorResolution contains the data required to sweep the anchor 36 // output. If the channel type doesn't include anchors, the value of 37 // this field will be nil. 38 AnchorResolution *lnwallet.AnchorResolution 39 40 // BreachResolution contains the data required to manage the lifecycle 41 // of a breach in the ChannelArbitrator. 42 BreachResolution *BreachResolution 43 } 44 45 // IsEmpty returns true if the set of resolutions is "empty". A resolution is 46 // empty if: our commitment output has been trimmed, we don't have any 47 // incoming or outgoing HTLC's active, there is no anchor output to sweep, or 48 // there are no breached outputs to resolve. 49 func (c *ContractResolutions) IsEmpty() bool { 50 return c.CommitResolution == nil && 51 len(c.HtlcResolutions.IncomingHTLCs) == 0 && 52 len(c.HtlcResolutions.OutgoingHTLCs) == 0 && 53 c.AnchorResolution == nil && c.BreachResolution == nil 54 } 55 56 // ArbitratorLog is the primary source of persistent storage for the 57 // ChannelArbitrator. The log stores the current state of the 58 // ChannelArbitrator's internal state machine, any items that are required to 59 // properly make a state transition, and any unresolved contracts. 60 type ArbitratorLog interface { 61 // TODO(roasbeef): document on interface the errors expected to be 62 // returned 63 64 // CurrentState returns the current state of the ChannelArbitrator. It 65 // takes an optional database transaction, which will be used if it is 66 // non-nil, otherwise the lookup will be done in its own transaction. 67 CurrentState(tx kvdb.RTx) (ArbitratorState, error) 68 69 // CommitState persists, the current state of the chain attendant. 70 CommitState(ArbitratorState) error 71 72 // InsertUnresolvedContracts inserts a set of unresolved contracts into 73 // the log. The log will then persistently store each contract until 74 // they've been swapped out, or resolved. It takes a set of report which 75 // should be written to disk if as well if it is non-nil. 76 InsertUnresolvedContracts(reports []*channeldb.ResolverReport, 77 resolvers ...ContractResolver) error 78 79 // FetchUnresolvedContracts returns all unresolved contracts that have 80 // been previously written to the log. 81 FetchUnresolvedContracts() ([]ContractResolver, error) 82 83 // SwapContract performs an atomic swap of the old contract for the new 84 // contract. This method is used when after a contract has been fully 85 // resolved, it produces another contract that needs to be resolved. 86 SwapContract(old ContractResolver, new ContractResolver) error 87 88 // ResolveContract marks a contract as fully resolved. Once a contract 89 // has been fully resolved, it is deleted from persistent storage. 90 ResolveContract(ContractResolver) error 91 92 // LogContractResolutions stores a complete contract resolution for the 93 // contract under watch. This method will be called once the 94 // ChannelArbitrator either force closes a channel, or detects that the 95 // remote party has broadcast their commitment on chain. 96 LogContractResolutions(*ContractResolutions) error 97 98 // FetchContractResolutions fetches the set of previously stored 99 // contract resolutions from persistent storage. 100 FetchContractResolutions() (*ContractResolutions, error) 101 102 // InsertConfirmedCommitSet stores the known set of active HTLCs at the 103 // time channel closure. We'll use this to reconstruct our set of chain 104 // actions anew based on the confirmed and pending commitment state. 105 InsertConfirmedCommitSet(c *CommitSet) error 106 107 // FetchConfirmedCommitSet fetches the known confirmed active HTLC set 108 // from the database. It takes an optional database transaction, which 109 // will be used if it is non-nil, otherwise the lookup will be done in 110 // its own transaction. 111 FetchConfirmedCommitSet(tx kvdb.RTx) (*CommitSet, error) 112 113 // FetchChainActions attempts to fetch the set of previously stored 114 // chain actions. We'll use this upon restart to properly advance our 115 // state machine forward. 116 // 117 // NOTE: This method only exists in order to be able to serve nodes had 118 // channels in the process of closing before the CommitSet struct was 119 // introduced. 120 FetchChainActions() (ChainActionMap, error) 121 122 // WipeHistory is to be called ONLY once *all* contracts have been 123 // fully resolved, and the channel closure if finalized. This method 124 // will delete all on-disk state within the persistent log. 125 WipeHistory() error 126 } 127 128 // ArbitratorState is an enum that details the current state of the 129 // ChannelArbitrator's state machine. 130 type ArbitratorState uint8 131 132 const ( 133 // While some state transition is allowed, certain transitions are not 134 // possible. Listed below is the full state transition map which 135 // contains all possible paths. We start at StateDefault and end at 136 // StateFullyResolved, or StateError(not listed as its a possible state 137 // in every path). The format is, 138 // -> state: conditions we switch to this state. 139 // 140 // StateDefault 141 // | 142 // |-> StateDefault: no actions and chain trigger 143 // | 144 // |-> StateBroadcastCommit: chain/user trigger 145 // | | 146 // | |-> StateCommitmentBroadcasted: chain/user trigger 147 // | | | 148 // | | |-> StateCommitmentBroadcasted: chain/user trigger 149 // | | | 150 // | | |-> StateContractClosed: local/remote/breach close trigger 151 // | | | | 152 // | | | |-> StateWaitingFullResolution: contract resolutions not empty 153 // | | | | | 154 // | | | | |-> StateWaitingFullResolution: contract resolutions not empty 155 // | | | | | 156 // | | | | |-> StateFullyResolved: contract resolutions empty 157 // | | | | 158 // | | | |-> StateFullyResolved: contract resolutions empty 159 // | | | 160 // | | |-> StateFullyResolved: coop/breach(legacy) close trigger 161 // | | 162 // | |-> StateContractClosed: local/remote/breach close trigger 163 // | | | 164 // | | |-> StateWaitingFullResolution: contract resolutions not empty 165 // | | | | 166 // | | | |-> StateWaitingFullResolution: contract resolutions not empty 167 // | | | | 168 // | | | |-> StateFullyResolved: contract resolutions empty 169 // | | | 170 // | | |-> StateFullyResolved: contract resolutions empty 171 // | | 172 // | |-> StateFullyResolved: coop/breach(legacy) close trigger 173 // | 174 // |-> StateContractClosed: local/remote/breach close trigger 175 // | | 176 // | |-> StateWaitingFullResolution: contract resolutions not empty 177 // | | | 178 // | | |-> StateWaitingFullResolution: contract resolutions not empty 179 // | | | 180 // | | |-> StateFullyResolved: contract resolutions empty 181 // | | 182 // | |-> StateFullyResolved: contract resolutions empty 183 // | 184 // |-> StateFullyResolved: coop/breach(legacy) close trigger 185 186 // StateDefault is the default state. In this state, no major actions 187 // need to be executed. 188 StateDefault ArbitratorState = 0 189 190 // StateBroadcastCommit is a state that indicates that the attendant 191 // has decided to broadcast the commitment transaction, but hasn't done 192 // so yet. 193 StateBroadcastCommit ArbitratorState = 1 194 195 // StateCommitmentBroadcasted is a state that indicates that the 196 // attendant has broadcasted the commitment transaction, and is now 197 // waiting for it to confirm. 198 StateCommitmentBroadcasted ArbitratorState = 6 199 200 // StateContractClosed is a state that indicates the contract has 201 // already been "closed", meaning the commitment is confirmed on chain. 202 // At this point, we can now examine our active contracts, in order to 203 // create the proper resolver for each one. 204 StateContractClosed ArbitratorState = 2 205 206 // StateWaitingFullResolution is a state that indicates that the 207 // commitment transaction has been confirmed, and the attendant is now 208 // waiting for all unresolved contracts to be fully resolved. 209 StateWaitingFullResolution ArbitratorState = 3 210 211 // StateFullyResolved is the final state of the attendant. In this 212 // state, all related contracts have been resolved, and the attendant 213 // can now be garbage collected. 214 StateFullyResolved ArbitratorState = 4 215 216 // StateError is the only error state of the resolver. If we enter this 217 // state, then we cannot proceed with manual intervention as a state 218 // transition failed. 219 StateError ArbitratorState = 5 220 ) 221 222 // String returns a human readable string describing the ArbitratorState. 223 func (a ArbitratorState) String() string { 224 switch a { 225 case StateDefault: 226 return "StateDefault" 227 228 case StateBroadcastCommit: 229 return "StateBroadcastCommit" 230 231 case StateCommitmentBroadcasted: 232 return "StateCommitmentBroadcasted" 233 234 case StateContractClosed: 235 return "StateContractClosed" 236 237 case StateWaitingFullResolution: 238 return "StateWaitingFullResolution" 239 240 case StateFullyResolved: 241 return "StateFullyResolved" 242 243 case StateError: 244 return "StateError" 245 246 default: 247 return "unknown state" 248 } 249 } 250 251 // resolverType is an enum that enumerates the various types of resolvers. When 252 // writing resolvers to disk, we prepend this to the raw bytes stored. This 253 // allows us to properly decode the resolver into the proper type. 254 type resolverType uint8 255 256 const ( 257 // resolverTimeout is the type of a resolver that's tasked with 258 // resolving an outgoing HTLC that is very close to timing out. 259 resolverTimeout resolverType = 0 260 261 // resolverSuccess is the type of a resolver that's tasked with 262 // resolving an incoming HTLC that we already know the preimage of. 263 resolverSuccess resolverType = 1 264 265 // resolverOutgoingContest is the type of a resolver that's tasked with 266 // resolving an outgoing HTLC that hasn't yet timed out. 267 resolverOutgoingContest resolverType = 2 268 269 // resolverIncomingContest is the type of a resolver that's tasked with 270 // resolving an incoming HTLC that we don't yet know the preimage to. 271 resolverIncomingContest resolverType = 3 272 273 // resolverUnilateralSweep is the type of resolver that's tasked with 274 // sweeping out direct commitment output form the remote party's 275 // commitment transaction. 276 resolverUnilateralSweep resolverType = 4 277 278 // resolverBreach is the type of resolver that manages a contract 279 // breach on-chain. 280 resolverBreach resolverType = 5 281 ) 282 283 // resolverIDLen is the size of the resolver ID key. This is 36 bytes as we get 284 // 32 bytes from the hash of the prev tx, and 4 bytes for the output index. 285 const resolverIDLen = 36 286 287 // resolverID is a key that uniquely identifies a resolver within a particular 288 // chain. For this value we use the full outpoint of the resolver. 289 type resolverID [resolverIDLen]byte 290 291 // newResolverID returns a resolverID given the outpoint of a contract. 292 func newResolverID(op wire.OutPoint) resolverID { 293 var r resolverID 294 295 copy(r[:], op.Hash[:]) 296 297 endian.PutUint32(r[32:], op.Index) 298 299 return r 300 } 301 302 // logScope is a key that we use to scope the storage of a ChannelArbitrator 303 // within the global log. We use this key to create a unique bucket within the 304 // database and ensure that we don't have any key collisions. The log's scope 305 // is define as: chainHash || chanPoint, where chanPoint is the chan point of 306 // the original channel. 307 type logScope [32 + 36]byte 308 309 // newLogScope creates a new logScope key from the passed chainhash and 310 // chanPoint. 311 func newLogScope(chain chainhash.Hash, op wire.OutPoint) (*logScope, error) { 312 var l logScope 313 b := bytes.NewBuffer(l[0:0]) 314 315 if _, err := b.Write(chain[:]); err != nil { 316 return nil, err 317 } 318 if _, err := b.Write(op.Hash[:]); err != nil { 319 return nil, err 320 } 321 322 if err := binary.Write(b, endian, op.Index); err != nil { 323 return nil, err 324 } 325 326 return &l, nil 327 } 328 329 var ( 330 // stateKey is the key that we use to store the current state of the 331 // arbitrator. 332 stateKey = []byte("state") 333 334 // contractsBucketKey is the bucket within the logScope that will store 335 // all the active unresolved contracts. 336 contractsBucketKey = []byte("contractkey") 337 338 // resolutionsKey is the key under the logScope that we'll use to store 339 // the full set of resolutions for a channel. 340 resolutionsKey = []byte("resolutions") 341 342 // resolutionsSignDetailsKey is the key under the logScope where we 343 // will store input.SignDetails for each HTLC resolution. If this is 344 // not found under the logScope, it means it was written before 345 // SignDetails was introduced, and should be set nil for each HTLC 346 // resolution. 347 resolutionsSignDetailsKey = []byte("resolutions-sign-details") 348 349 // anchorResolutionKey is the key under the logScope that we'll use to 350 // store the anchor resolution, if any. 351 anchorResolutionKey = []byte("anchor-resolution") 352 353 // breachResolutionKey is the key under the logScope that we'll use to 354 // store the breach resolution, if any. This is used rather than the 355 // resolutionsKey. 356 breachResolutionKey = []byte("breach-resolution") 357 358 // actionsBucketKey is the key under the logScope that we'll use to 359 // store all chain actions once they're determined. 360 actionsBucketKey = []byte("chain-actions") 361 362 // commitSetKey is the primary key under the logScope that we'll use to 363 // store the confirmed active HTLC sets once we learn that a channel 364 // has closed out on chain. 365 commitSetKey = []byte("commit-set") 366 ) 367 368 var ( 369 // errScopeBucketNoExist is returned when we can't find the proper 370 // bucket for an arbitrator's scope. 371 errScopeBucketNoExist = fmt.Errorf("scope bucket not found") 372 373 // errNoContracts is returned when no contracts are found within the 374 // log. 375 errNoContracts = fmt.Errorf("no stored contracts") 376 377 // errNoResolutions is returned when the log doesn't contain any active 378 // chain resolutions. 379 errNoResolutions = fmt.Errorf("no contract resolutions exist") 380 381 // errNoActions is retuned when the log doesn't contain any stored 382 // chain actions. 383 errNoActions = fmt.Errorf("no chain actions exist") 384 385 // errNoCommitSet is return when the log doesn't contained a CommitSet. 386 // This can happen if the channel hasn't closed yet, or a client is 387 // running an older version that didn't yet write this state. 388 errNoCommitSet = fmt.Errorf("no commit set exists") 389 ) 390 391 // boltArbitratorLog is an implementation of the ArbitratorLog interface backed 392 // by a bolt DB instance. 393 type boltArbitratorLog struct { 394 db kvdb.Backend 395 396 cfg ChannelArbitratorConfig 397 398 scopeKey logScope 399 } 400 401 // newBoltArbitratorLog returns a new instance of the bboltArbitratorLog given 402 // an arbitrator config, and the items needed to create its log scope. 403 func newBoltArbitratorLog(db kvdb.Backend, cfg ChannelArbitratorConfig, 404 chainHash chainhash.Hash, chanPoint wire.OutPoint) (*boltArbitratorLog, error) { 405 406 scope, err := newLogScope(chainHash, chanPoint) 407 if err != nil { 408 return nil, err 409 } 410 411 return &boltArbitratorLog{ 412 db: db, 413 cfg: cfg, 414 scopeKey: *scope, 415 }, nil 416 } 417 418 // A compile time check to ensure bboltArbitratorLog meets the ArbitratorLog 419 // interface. 420 var _ ArbitratorLog = (*boltArbitratorLog)(nil) 421 422 func fetchContractReadBucket(tx kvdb.RTx, scopeKey []byte) (kvdb.RBucket, error) { 423 scopeBucket := tx.ReadBucket(scopeKey) 424 if scopeBucket == nil { 425 return nil, errScopeBucketNoExist 426 } 427 428 contractBucket := scopeBucket.NestedReadBucket(contractsBucketKey) 429 if contractBucket == nil { 430 return nil, errNoContracts 431 } 432 433 return contractBucket, nil 434 } 435 436 func fetchContractWriteBucket(tx kvdb.RwTx, scopeKey []byte) (kvdb.RwBucket, error) { 437 scopeBucket, err := tx.CreateTopLevelBucket(scopeKey) 438 if err != nil { 439 return nil, err 440 } 441 442 contractBucket, err := scopeBucket.CreateBucketIfNotExists( 443 contractsBucketKey, 444 ) 445 if err != nil { 446 return nil, err 447 } 448 449 return contractBucket, nil 450 } 451 452 // writeResolver is a helper method that writes a contract resolver and stores 453 // it it within the passed contractBucket using its unique resolutionsKey key. 454 func (b *boltArbitratorLog) writeResolver(contractBucket kvdb.RwBucket, 455 res ContractResolver) error { 456 457 // Only persist resolvers that are stateful. Stateless resolvers don't 458 // expose a resolver key. 459 resKey := res.ResolverKey() 460 if resKey == nil { 461 return nil 462 } 463 464 // First, we'll write to the buffer the type of this resolver. Using 465 // this byte, we can later properly deserialize the resolver properly. 466 var ( 467 buf bytes.Buffer 468 rType resolverType 469 ) 470 switch res.(type) { 471 case *htlcTimeoutResolver: 472 rType = resolverTimeout 473 case *htlcSuccessResolver: 474 rType = resolverSuccess 475 case *htlcOutgoingContestResolver: 476 rType = resolverOutgoingContest 477 case *htlcIncomingContestResolver: 478 rType = resolverIncomingContest 479 case *commitSweepResolver: 480 rType = resolverUnilateralSweep 481 case *breachResolver: 482 rType = resolverBreach 483 } 484 if _, err := buf.Write([]byte{byte(rType)}); err != nil { 485 return err 486 } 487 488 // With the type of the resolver written, we can then write out the raw 489 // bytes of the resolver itself. 490 if err := res.Encode(&buf); err != nil { 491 return err 492 } 493 494 return contractBucket.Put(resKey, buf.Bytes()) 495 } 496 497 // CurrentState returns the current state of the ChannelArbitrator. It takes an 498 // optional database transaction, which will be used if it is non-nil, otherwise 499 // the lookup will be done in its own transaction. 500 // 501 // NOTE: Part of the ContractResolver interface. 502 func (b *boltArbitratorLog) CurrentState(tx kvdb.RTx) (ArbitratorState, error) { 503 var ( 504 s ArbitratorState 505 err error 506 ) 507 508 if tx != nil { 509 s, err = b.currentState(tx) 510 } else { 511 err = kvdb.View(b.db, func(tx kvdb.RTx) error { 512 s, err = b.currentState(tx) 513 return err 514 }, func() { 515 s = 0 516 }) 517 } 518 519 if err != nil && err != errScopeBucketNoExist { 520 return s, err 521 } 522 523 return s, nil 524 } 525 526 func (b *boltArbitratorLog) currentState(tx kvdb.RTx) (ArbitratorState, error) { 527 scopeBucket := tx.ReadBucket(b.scopeKey[:]) 528 if scopeBucket == nil { 529 return 0, errScopeBucketNoExist 530 } 531 532 stateBytes := scopeBucket.Get(stateKey) 533 if stateBytes == nil { 534 return 0, nil 535 } 536 537 return ArbitratorState(stateBytes[0]), nil 538 } 539 540 // CommitState persists, the current state of the chain attendant. 541 // 542 // NOTE: Part of the ContractResolver interface. 543 func (b *boltArbitratorLog) CommitState(s ArbitratorState) error { 544 return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { 545 scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:]) 546 if err != nil { 547 return err 548 } 549 550 return scopeBucket.Put(stateKey, []byte{uint8(s)}) 551 }) 552 } 553 554 // FetchUnresolvedContracts returns all unresolved contracts that have been 555 // previously written to the log. 556 // 557 // NOTE: Part of the ContractResolver interface. 558 func (b *boltArbitratorLog) FetchUnresolvedContracts() ([]ContractResolver, error) { 559 resolverCfg := ResolverConfig{ 560 ChannelArbitratorConfig: b.cfg, 561 Checkpoint: b.checkpointContract, 562 } 563 var contracts []ContractResolver 564 err := kvdb.View(b.db, func(tx kvdb.RTx) error { 565 contractBucket, err := fetchContractReadBucket(tx, b.scopeKey[:]) 566 if err != nil { 567 return err 568 } 569 570 return contractBucket.ForEach(func(resKey, resBytes []byte) error { 571 if len(resKey) != resolverIDLen { 572 return nil 573 } 574 575 var res ContractResolver 576 577 // We'll snip off the first byte of the raw resolver 578 // bytes in order to extract what type of resolver 579 // we're about to encode. 580 resType := resolverType(resBytes[0]) 581 582 // Then we'll create a reader using the remaining 583 // bytes. 584 resReader := bytes.NewReader(resBytes[1:]) 585 586 switch resType { 587 case resolverTimeout: 588 res, err = newTimeoutResolverFromReader( 589 resReader, resolverCfg, 590 ) 591 592 case resolverSuccess: 593 res, err = newSuccessResolverFromReader( 594 resReader, resolverCfg, 595 ) 596 597 case resolverOutgoingContest: 598 res, err = newOutgoingContestResolverFromReader( 599 resReader, resolverCfg, 600 ) 601 602 case resolverIncomingContest: 603 res, err = newIncomingContestResolverFromReader( 604 resReader, resolverCfg, 605 ) 606 607 case resolverUnilateralSweep: 608 res, err = newCommitSweepResolverFromReader( 609 resReader, resolverCfg, 610 ) 611 612 case resolverBreach: 613 res, err = newBreachResolverFromReader( 614 resReader, resolverCfg, 615 ) 616 617 default: 618 return fmt.Errorf("unknown resolver type: %v", resType) 619 } 620 621 if err != nil { 622 return err 623 } 624 625 contracts = append(contracts, res) 626 return nil 627 }) 628 }, func() { 629 contracts = nil 630 }) 631 if err != nil && err != errScopeBucketNoExist && err != errNoContracts { 632 return nil, err 633 } 634 635 return contracts, nil 636 } 637 638 // InsertUnresolvedContracts inserts a set of unresolved contracts into the 639 // log. The log will then persistently store each contract until they've been 640 // swapped out, or resolved. 641 // 642 // NOTE: Part of the ContractResolver interface. 643 func (b *boltArbitratorLog) InsertUnresolvedContracts(reports []*channeldb.ResolverReport, 644 resolvers ...ContractResolver) error { 645 646 return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { 647 contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:]) 648 if err != nil { 649 return err 650 } 651 652 for _, resolver := range resolvers { 653 err = b.writeResolver(contractBucket, resolver) 654 if err != nil { 655 return err 656 } 657 } 658 659 // Persist any reports that are present. 660 for _, report := range reports { 661 err := b.cfg.PutResolverReport(tx, report) 662 if err != nil { 663 return err 664 } 665 } 666 667 return nil 668 }) 669 } 670 671 // SwapContract performs an atomic swap of the old contract for the new 672 // contract. This method is used when after a contract has been fully resolved, 673 // it produces another contract that needs to be resolved. 674 // 675 // NOTE: Part of the ContractResolver interface. 676 func (b *boltArbitratorLog) SwapContract(oldContract, newContract ContractResolver) error { 677 return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { 678 contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:]) 679 if err != nil { 680 return err 681 } 682 683 oldContractkey := oldContract.ResolverKey() 684 if err := contractBucket.Delete(oldContractkey); err != nil { 685 return err 686 } 687 688 return b.writeResolver(contractBucket, newContract) 689 }) 690 } 691 692 // ResolveContract marks a contract as fully resolved. Once a contract has been 693 // fully resolved, it is deleted from persistent storage. 694 // 695 // NOTE: Part of the ContractResolver interface. 696 func (b *boltArbitratorLog) ResolveContract(res ContractResolver) error { 697 return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { 698 contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:]) 699 if err != nil { 700 return err 701 } 702 703 resKey := res.ResolverKey() 704 return contractBucket.Delete(resKey) 705 }) 706 } 707 708 // LogContractResolutions stores a set of chain actions which are derived from 709 // our set of active contracts, and the on-chain state. We'll write this et of 710 // cations when: we decide to go on-chain to resolve a contract, or we detect 711 // that the remote party has gone on-chain. 712 // 713 // NOTE: Part of the ContractResolver interface. 714 func (b *boltArbitratorLog) LogContractResolutions(c *ContractResolutions) error { 715 return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { 716 scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:]) 717 if err != nil { 718 return err 719 } 720 721 var b bytes.Buffer 722 723 if _, err := b.Write(c.CommitHash[:]); err != nil { 724 return err 725 } 726 727 // First, we'll write out the commit output's resolution. 728 if c.CommitResolution == nil { 729 if err := binary.Write(&b, endian, false); err != nil { 730 return err 731 } 732 } else { 733 if err := binary.Write(&b, endian, true); err != nil { 734 return err 735 } 736 err = encodeCommitResolution(&b, c.CommitResolution) 737 if err != nil { 738 return err 739 } 740 } 741 742 // As we write the HTLC resolutions, we'll serialize the sign 743 // details for each, to store under a new key. 744 var signDetailsBuf bytes.Buffer 745 746 // With the output for the commitment transaction written, we 747 // can now write out the resolutions for the incoming and 748 // outgoing HTLC's. 749 numIncoming := uint32(len(c.HtlcResolutions.IncomingHTLCs)) 750 if err := binary.Write(&b, endian, numIncoming); err != nil { 751 return err 752 } 753 for _, htlc := range c.HtlcResolutions.IncomingHTLCs { 754 err := encodeIncomingResolution(&b, &htlc) 755 if err != nil { 756 return err 757 } 758 759 err = encodeSignDetails(&signDetailsBuf, htlc.SignDetails) 760 if err != nil { 761 return err 762 } 763 } 764 numOutgoing := uint32(len(c.HtlcResolutions.OutgoingHTLCs)) 765 if err := binary.Write(&b, endian, numOutgoing); err != nil { 766 return err 767 } 768 for _, htlc := range c.HtlcResolutions.OutgoingHTLCs { 769 err := encodeOutgoingResolution(&b, &htlc) 770 if err != nil { 771 return err 772 } 773 774 err = encodeSignDetails(&signDetailsBuf, htlc.SignDetails) 775 if err != nil { 776 return err 777 } 778 } 779 780 // Put the resolutions under the resolutionsKey. 781 err = scopeBucket.Put(resolutionsKey, b.Bytes()) 782 if err != nil { 783 return err 784 } 785 786 // We'll put the serialized sign details under its own key to 787 // stay backwards compatible. 788 err = scopeBucket.Put( 789 resolutionsSignDetailsKey, signDetailsBuf.Bytes(), 790 ) 791 if err != nil { 792 return err 793 } 794 795 // Write out the anchor resolution if present. 796 if c.AnchorResolution != nil { 797 var b bytes.Buffer 798 err := encodeAnchorResolution(&b, c.AnchorResolution) 799 if err != nil { 800 return err 801 } 802 803 err = scopeBucket.Put(anchorResolutionKey, b.Bytes()) 804 if err != nil { 805 return err 806 } 807 } 808 809 // Write out the breach resolution if present. 810 if c.BreachResolution != nil { 811 var b bytes.Buffer 812 err := encodeBreachResolution(&b, c.BreachResolution) 813 if err != nil { 814 return err 815 } 816 817 err = scopeBucket.Put(breachResolutionKey, b.Bytes()) 818 if err != nil { 819 return err 820 } 821 } 822 823 return nil 824 }) 825 } 826 827 // FetchContractResolutions fetches the set of previously stored contract 828 // resolutions from persistent storage. 829 // 830 // NOTE: Part of the ContractResolver interface. 831 func (b *boltArbitratorLog) FetchContractResolutions() (*ContractResolutions, error) { 832 var c *ContractResolutions 833 err := kvdb.View(b.db, func(tx kvdb.RTx) error { 834 scopeBucket := tx.ReadBucket(b.scopeKey[:]) 835 if scopeBucket == nil { 836 return errScopeBucketNoExist 837 } 838 839 resolutionBytes := scopeBucket.Get(resolutionsKey) 840 if resolutionBytes == nil { 841 return errNoResolutions 842 } 843 844 resReader := bytes.NewReader(resolutionBytes) 845 846 _, err := io.ReadFull(resReader, c.CommitHash[:]) 847 if err != nil { 848 return err 849 } 850 851 // First, we'll attempt to read out the commit resolution (if 852 // it exists). 853 var haveCommitRes bool 854 err = binary.Read(resReader, endian, &haveCommitRes) 855 if err != nil { 856 return err 857 } 858 if haveCommitRes { 859 c.CommitResolution = &lnwallet.CommitOutputResolution{} 860 err = decodeCommitResolution( 861 resReader, c.CommitResolution, 862 ) 863 if err != nil { 864 return err 865 } 866 } 867 868 var ( 869 numIncoming uint32 870 numOutgoing uint32 871 ) 872 873 // Next, we'll read out the incoming and outgoing HTLC 874 // resolutions. 875 err = binary.Read(resReader, endian, &numIncoming) 876 if err != nil { 877 return err 878 } 879 c.HtlcResolutions.IncomingHTLCs = make([]lnwallet.IncomingHtlcResolution, numIncoming) 880 for i := uint32(0); i < numIncoming; i++ { 881 err := decodeIncomingResolution( 882 resReader, &c.HtlcResolutions.IncomingHTLCs[i], 883 ) 884 if err != nil { 885 return err 886 } 887 } 888 889 err = binary.Read(resReader, endian, &numOutgoing) 890 if err != nil { 891 return err 892 } 893 c.HtlcResolutions.OutgoingHTLCs = make([]lnwallet.OutgoingHtlcResolution, numOutgoing) 894 for i := uint32(0); i < numOutgoing; i++ { 895 err := decodeOutgoingResolution( 896 resReader, &c.HtlcResolutions.OutgoingHTLCs[i], 897 ) 898 if err != nil { 899 return err 900 } 901 } 902 903 // Now we attempt to get the sign details for our HTLC 904 // resolutions. If not present the channel is of a type that 905 // doesn't need them. If present there will be SignDetails 906 // encoded for each HTLC resolution. 907 signDetailsBytes := scopeBucket.Get(resolutionsSignDetailsKey) 908 if signDetailsBytes != nil { 909 r := bytes.NewReader(signDetailsBytes) 910 911 // They will be encoded in the same order as the 912 // resolutions: firs incoming HTLCs, then outgoing. 913 for i := uint32(0); i < numIncoming; i++ { 914 htlc := &c.HtlcResolutions.IncomingHTLCs[i] 915 htlc.SignDetails, err = decodeSignDetails(r) 916 if err != nil { 917 return err 918 } 919 } 920 921 for i := uint32(0); i < numOutgoing; i++ { 922 htlc := &c.HtlcResolutions.OutgoingHTLCs[i] 923 htlc.SignDetails, err = decodeSignDetails(r) 924 if err != nil { 925 return err 926 } 927 } 928 } 929 930 anchorResBytes := scopeBucket.Get(anchorResolutionKey) 931 if anchorResBytes != nil { 932 c.AnchorResolution = &lnwallet.AnchorResolution{} 933 resReader := bytes.NewReader(anchorResBytes) 934 err := decodeAnchorResolution( 935 resReader, c.AnchorResolution, 936 ) 937 if err != nil { 938 return err 939 } 940 } 941 942 breachResBytes := scopeBucket.Get(breachResolutionKey) 943 if breachResBytes != nil { 944 c.BreachResolution = &BreachResolution{} 945 resReader := bytes.NewReader(breachResBytes) 946 err := decodeBreachResolution( 947 resReader, c.BreachResolution, 948 ) 949 if err != nil { 950 return err 951 } 952 } 953 954 return nil 955 }, func() { 956 c = &ContractResolutions{} 957 }) 958 if err != nil { 959 return nil, err 960 } 961 962 return c, err 963 } 964 965 // FetchChainActions attempts to fetch the set of previously stored chain 966 // actions. We'll use this upon restart to properly advance our state machine 967 // forward. 968 // 969 // NOTE: Part of the ContractResolver interface. 970 func (b *boltArbitratorLog) FetchChainActions() (ChainActionMap, error) { 971 var actionsMap ChainActionMap 972 973 err := kvdb.View(b.db, func(tx kvdb.RTx) error { 974 scopeBucket := tx.ReadBucket(b.scopeKey[:]) 975 if scopeBucket == nil { 976 return errScopeBucketNoExist 977 } 978 979 actionsBucket := scopeBucket.NestedReadBucket(actionsBucketKey) 980 if actionsBucket == nil { 981 return errNoActions 982 } 983 984 return actionsBucket.ForEach(func(action, htlcBytes []byte) error { 985 if htlcBytes == nil { 986 return nil 987 } 988 989 chainAction := ChainAction(action[0]) 990 991 htlcReader := bytes.NewReader(htlcBytes) 992 htlcs, err := channeldb.DeserializeHtlcs(htlcReader) 993 if err != nil { 994 return err 995 } 996 997 actionsMap[chainAction] = htlcs 998 999 return nil 1000 }) 1001 }, func() { 1002 actionsMap = make(ChainActionMap) 1003 }) 1004 if err != nil { 1005 return nil, err 1006 } 1007 1008 return actionsMap, nil 1009 } 1010 1011 // InsertConfirmedCommitSet stores the known set of active HTLCs at the time 1012 // channel closure. We'll use this to reconstruct our set of chain actions anew 1013 // based on the confirmed and pending commitment state. 1014 // 1015 // NOTE: Part of the ContractResolver interface. 1016 func (b *boltArbitratorLog) InsertConfirmedCommitSet(c *CommitSet) error { 1017 return kvdb.Batch(b.db, func(tx kvdb.RwTx) error { 1018 scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:]) 1019 if err != nil { 1020 return err 1021 } 1022 1023 var b bytes.Buffer 1024 if err := encodeCommitSet(&b, c); err != nil { 1025 return err 1026 } 1027 1028 return scopeBucket.Put(commitSetKey, b.Bytes()) 1029 }) 1030 } 1031 1032 // FetchConfirmedCommitSet fetches the known confirmed active HTLC set from the 1033 // database. It takes an optional database transaction, which will be used if it 1034 // is non-nil, otherwise the lookup will be done in its own transaction. 1035 // 1036 // NOTE: Part of the ContractResolver interface. 1037 func (b *boltArbitratorLog) FetchConfirmedCommitSet(tx kvdb.RTx) (*CommitSet, error) { 1038 if tx != nil { 1039 return b.fetchConfirmedCommitSet(tx) 1040 } 1041 1042 var c *CommitSet 1043 err := kvdb.View(b.db, func(tx kvdb.RTx) error { 1044 var err error 1045 c, err = b.fetchConfirmedCommitSet(tx) 1046 return err 1047 }, func() { 1048 c = nil 1049 }) 1050 if err != nil { 1051 return nil, err 1052 } 1053 1054 return c, nil 1055 } 1056 1057 func (b *boltArbitratorLog) fetchConfirmedCommitSet(tx kvdb.RTx) (*CommitSet, 1058 error) { 1059 1060 scopeBucket := tx.ReadBucket(b.scopeKey[:]) 1061 if scopeBucket == nil { 1062 return nil, errScopeBucketNoExist 1063 } 1064 1065 commitSetBytes := scopeBucket.Get(commitSetKey) 1066 if commitSetBytes == nil { 1067 return nil, errNoCommitSet 1068 } 1069 1070 return decodeCommitSet(bytes.NewReader(commitSetBytes)) 1071 } 1072 1073 // WipeHistory is to be called ONLY once *all* contracts have been fully 1074 // resolved, and the channel closure if finalized. This method will delete all 1075 // on-disk state within the persistent log. 1076 // 1077 // NOTE: Part of the ContractResolver interface. 1078 func (b *boltArbitratorLog) WipeHistory() error { 1079 return kvdb.Update(b.db, func(tx kvdb.RwTx) error { 1080 scopeBucket, err := tx.CreateTopLevelBucket(b.scopeKey[:]) 1081 if err != nil { 1082 return err 1083 } 1084 1085 // Once we have the main top-level bucket, we'll delete the key 1086 // that stores the state of the arbitrator. 1087 if err := scopeBucket.Delete(stateKey); err != nil { 1088 return err 1089 } 1090 1091 // Next, we'll delete any lingering contract state within the 1092 // contracts bucket by removing the bucket itself. 1093 err = scopeBucket.DeleteNestedBucket(contractsBucketKey) 1094 if err != nil && err != kvdb.ErrBucketNotFound { 1095 return err 1096 } 1097 1098 // Next, we'll delete storage of any lingering contract 1099 // resolutions. 1100 if err := scopeBucket.Delete(resolutionsKey); err != nil { 1101 return err 1102 } 1103 1104 err = scopeBucket.Delete(resolutionsSignDetailsKey) 1105 if err != nil { 1106 return err 1107 } 1108 1109 // We'll delete any chain actions that are still stored by 1110 // removing the enclosing bucket. 1111 err = scopeBucket.DeleteNestedBucket(actionsBucketKey) 1112 if err != nil && err != kvdb.ErrBucketNotFound { 1113 return err 1114 } 1115 1116 // Finally, we'll delete the enclosing bucket itself. 1117 return tx.DeleteTopLevelBucket(b.scopeKey[:]) 1118 }, func() {}) 1119 } 1120 1121 // checkpointContract is a private method that will be fed into 1122 // ContractResolver instances to checkpoint their state once they reach 1123 // milestones during contract resolution. If the report provided is non-nil, 1124 // it should also be recorded. 1125 func (b *boltArbitratorLog) checkpointContract(c ContractResolver, 1126 reports ...*channeldb.ResolverReport) error { 1127 1128 return kvdb.Update(b.db, func(tx kvdb.RwTx) error { 1129 contractBucket, err := fetchContractWriteBucket(tx, b.scopeKey[:]) 1130 if err != nil { 1131 return err 1132 } 1133 1134 if err := b.writeResolver(contractBucket, c); err != nil { 1135 return err 1136 } 1137 1138 for _, report := range reports { 1139 if err := b.cfg.PutResolverReport(tx, report); err != nil { 1140 return err 1141 } 1142 } 1143 1144 return nil 1145 }, func() {}) 1146 } 1147 1148 // encodeSignDetails encodes the gived SignDetails struct to the writer. 1149 // SignDetails is allowed to be nil, in which we will encode that it is not 1150 // present. 1151 func encodeSignDetails(w io.Writer, s *input.SignDetails) error { 1152 // If we don't have sign details, write false and return. 1153 if s == nil { 1154 return binary.Write(w, endian, false) 1155 } 1156 1157 // Otherwise write true, and the contents of the SignDetails. 1158 if err := binary.Write(w, endian, true); err != nil { 1159 return err 1160 } 1161 1162 err := input.WriteSignDescriptor(w, &s.SignDesc) 1163 if err != nil { 1164 return err 1165 } 1166 err = binary.Write(w, endian, uint32(s.SigHashType)) 1167 if err != nil { 1168 return err 1169 } 1170 1171 // Write the DER-encoded signature. 1172 b := s.PeerSig.Serialize() 1173 if err := wire.WriteVarBytes(w, 0, b); err != nil { 1174 return err 1175 } 1176 1177 return nil 1178 } 1179 1180 // decodeSignDetails extracts a single SignDetails from the reader. It is 1181 // allowed to return nil in case the SignDetails were empty. 1182 func decodeSignDetails(r io.Reader) (*input.SignDetails, error) { 1183 var present bool 1184 if err := binary.Read(r, endian, &present); err != nil { 1185 return nil, err 1186 } 1187 1188 // Simply return nil if the next SignDetails was not present. 1189 if !present { 1190 return nil, nil 1191 } 1192 1193 // Otherwise decode the elements of the SignDetails. 1194 s := input.SignDetails{} 1195 err := input.ReadSignDescriptor(r, &s.SignDesc) 1196 if err != nil { 1197 return nil, err 1198 } 1199 1200 var sigHash uint32 1201 err = binary.Read(r, endian, &sigHash) 1202 if err != nil { 1203 return nil, err 1204 } 1205 s.SigHashType = txscript.SigHashType(sigHash) 1206 1207 // Read DER-encoded signature. 1208 rawSig, err := wire.ReadVarBytes(r, 0, 200, "signature") 1209 if err != nil { 1210 return nil, err 1211 } 1212 sig, err := ecdsa.ParseDERSignature(rawSig) 1213 if err != nil { 1214 return nil, err 1215 } 1216 s.PeerSig = sig 1217 1218 return &s, nil 1219 } 1220 1221 func encodeIncomingResolution(w io.Writer, i *lnwallet.IncomingHtlcResolution) error { 1222 if _, err := w.Write(i.Preimage[:]); err != nil { 1223 return err 1224 } 1225 1226 if i.SignedSuccessTx == nil { 1227 if err := binary.Write(w, endian, false); err != nil { 1228 return err 1229 } 1230 } else { 1231 if err := binary.Write(w, endian, true); err != nil { 1232 return err 1233 } 1234 1235 if err := i.SignedSuccessTx.Serialize(w); err != nil { 1236 return err 1237 } 1238 } 1239 1240 if err := binary.Write(w, endian, i.CsvDelay); err != nil { 1241 return err 1242 } 1243 if _, err := w.Write(i.ClaimOutpoint.Hash[:]); err != nil { 1244 return err 1245 } 1246 if err := binary.Write(w, endian, i.ClaimOutpoint.Index); err != nil { 1247 return err 1248 } 1249 err := input.WriteSignDescriptor(w, &i.SweepSignDesc) 1250 if err != nil { 1251 return err 1252 } 1253 1254 return nil 1255 } 1256 1257 func decodeIncomingResolution(r io.Reader, h *lnwallet.IncomingHtlcResolution) error { 1258 if _, err := io.ReadFull(r, h.Preimage[:]); err != nil { 1259 return err 1260 } 1261 1262 var txPresent bool 1263 if err := binary.Read(r, endian, &txPresent); err != nil { 1264 return err 1265 } 1266 if txPresent { 1267 h.SignedSuccessTx = &wire.MsgTx{} 1268 if err := h.SignedSuccessTx.Deserialize(r); err != nil { 1269 return err 1270 } 1271 } 1272 1273 err := binary.Read(r, endian, &h.CsvDelay) 1274 if err != nil { 1275 return err 1276 } 1277 _, err = io.ReadFull(r, h.ClaimOutpoint.Hash[:]) 1278 if err != nil { 1279 return err 1280 } 1281 err = binary.Read(r, endian, &h.ClaimOutpoint.Index) 1282 if err != nil { 1283 return err 1284 } 1285 1286 return input.ReadSignDescriptor(r, &h.SweepSignDesc) 1287 } 1288 1289 func encodeOutgoingResolution(w io.Writer, o *lnwallet.OutgoingHtlcResolution) error { 1290 if err := binary.Write(w, endian, o.Expiry); err != nil { 1291 return err 1292 } 1293 1294 if o.SignedTimeoutTx == nil { 1295 if err := binary.Write(w, endian, false); err != nil { 1296 return err 1297 } 1298 } else { 1299 if err := binary.Write(w, endian, true); err != nil { 1300 return err 1301 } 1302 1303 if err := o.SignedTimeoutTx.Serialize(w); err != nil { 1304 return err 1305 } 1306 } 1307 1308 if err := binary.Write(w, endian, o.CsvDelay); err != nil { 1309 return err 1310 } 1311 if _, err := w.Write(o.ClaimOutpoint.Hash[:]); err != nil { 1312 return err 1313 } 1314 if err := binary.Write(w, endian, o.ClaimOutpoint.Index); err != nil { 1315 return err 1316 } 1317 1318 return input.WriteSignDescriptor(w, &o.SweepSignDesc) 1319 } 1320 1321 func decodeOutgoingResolution(r io.Reader, o *lnwallet.OutgoingHtlcResolution) error { 1322 err := binary.Read(r, endian, &o.Expiry) 1323 if err != nil { 1324 return err 1325 } 1326 1327 var txPresent bool 1328 if err := binary.Read(r, endian, &txPresent); err != nil { 1329 return err 1330 } 1331 if txPresent { 1332 o.SignedTimeoutTx = &wire.MsgTx{} 1333 if err := o.SignedTimeoutTx.Deserialize(r); err != nil { 1334 return err 1335 } 1336 } 1337 1338 err = binary.Read(r, endian, &o.CsvDelay) 1339 if err != nil { 1340 return err 1341 } 1342 _, err = io.ReadFull(r, o.ClaimOutpoint.Hash[:]) 1343 if err != nil { 1344 return err 1345 } 1346 err = binary.Read(r, endian, &o.ClaimOutpoint.Index) 1347 if err != nil { 1348 return err 1349 } 1350 1351 return input.ReadSignDescriptor(r, &o.SweepSignDesc) 1352 } 1353 1354 func encodeCommitResolution(w io.Writer, 1355 c *lnwallet.CommitOutputResolution) error { 1356 1357 if _, err := w.Write(c.SelfOutPoint.Hash[:]); err != nil { 1358 return err 1359 } 1360 err := binary.Write(w, endian, c.SelfOutPoint.Index) 1361 if err != nil { 1362 return err 1363 } 1364 1365 err = input.WriteSignDescriptor(w, &c.SelfOutputSignDesc) 1366 if err != nil { 1367 return err 1368 } 1369 1370 return binary.Write(w, endian, c.MaturityDelay) 1371 } 1372 1373 func decodeCommitResolution(r io.Reader, 1374 c *lnwallet.CommitOutputResolution) error { 1375 1376 _, err := io.ReadFull(r, c.SelfOutPoint.Hash[:]) 1377 if err != nil { 1378 return err 1379 } 1380 err = binary.Read(r, endian, &c.SelfOutPoint.Index) 1381 if err != nil { 1382 return err 1383 } 1384 1385 err = input.ReadSignDescriptor(r, &c.SelfOutputSignDesc) 1386 if err != nil { 1387 return err 1388 } 1389 1390 return binary.Read(r, endian, &c.MaturityDelay) 1391 } 1392 1393 func encodeAnchorResolution(w io.Writer, 1394 a *lnwallet.AnchorResolution) error { 1395 1396 if _, err := w.Write(a.CommitAnchor.Hash[:]); err != nil { 1397 return err 1398 } 1399 err := binary.Write(w, endian, a.CommitAnchor.Index) 1400 if err != nil { 1401 return err 1402 } 1403 1404 return input.WriteSignDescriptor(w, &a.AnchorSignDescriptor) 1405 } 1406 1407 func decodeAnchorResolution(r io.Reader, 1408 a *lnwallet.AnchorResolution) error { 1409 1410 _, err := io.ReadFull(r, a.CommitAnchor.Hash[:]) 1411 if err != nil { 1412 return err 1413 } 1414 err = binary.Read(r, endian, &a.CommitAnchor.Index) 1415 if err != nil { 1416 return err 1417 } 1418 1419 return input.ReadSignDescriptor(r, &a.AnchorSignDescriptor) 1420 } 1421 1422 func encodeBreachResolution(w io.Writer, b *BreachResolution) error { 1423 if _, err := w.Write(b.FundingOutPoint.Hash[:]); err != nil { 1424 return err 1425 } 1426 return binary.Write(w, endian, b.FundingOutPoint.Index) 1427 } 1428 1429 func decodeBreachResolution(r io.Reader, b *BreachResolution) error { 1430 _, err := io.ReadFull(r, b.FundingOutPoint.Hash[:]) 1431 if err != nil { 1432 return err 1433 } 1434 return binary.Read(r, endian, &b.FundingOutPoint.Index) 1435 } 1436 1437 func encodeHtlcSetKey(w io.Writer, h *HtlcSetKey) error { 1438 err := binary.Write(w, endian, h.IsRemote) 1439 if err != nil { 1440 return err 1441 } 1442 return binary.Write(w, endian, h.IsPending) 1443 } 1444 1445 func encodeCommitSet(w io.Writer, c *CommitSet) error { 1446 if err := encodeHtlcSetKey(w, c.ConfCommitKey); err != nil { 1447 return err 1448 } 1449 1450 numSets := uint8(len(c.HtlcSets)) 1451 if err := binary.Write(w, endian, numSets); err != nil { 1452 return err 1453 } 1454 1455 for htlcSetKey, htlcs := range c.HtlcSets { 1456 htlcSetKey := htlcSetKey 1457 if err := encodeHtlcSetKey(w, &htlcSetKey); err != nil { 1458 return err 1459 } 1460 1461 if err := channeldb.SerializeHtlcs(w, htlcs...); err != nil { 1462 return err 1463 } 1464 } 1465 1466 return nil 1467 } 1468 1469 func decodeHtlcSetKey(r io.Reader, h *HtlcSetKey) error { 1470 err := binary.Read(r, endian, &h.IsRemote) 1471 if err != nil { 1472 return err 1473 } 1474 1475 return binary.Read(r, endian, &h.IsPending) 1476 } 1477 1478 func decodeCommitSet(r io.Reader) (*CommitSet, error) { 1479 c := &CommitSet{ 1480 ConfCommitKey: &HtlcSetKey{}, 1481 HtlcSets: make(map[HtlcSetKey][]channeldb.HTLC), 1482 } 1483 1484 if err := decodeHtlcSetKey(r, c.ConfCommitKey); err != nil { 1485 return nil, err 1486 } 1487 1488 var numSets uint8 1489 if err := binary.Read(r, endian, &numSets); err != nil { 1490 return nil, err 1491 } 1492 1493 for i := uint8(0); i < numSets; i++ { 1494 var htlcSetKey HtlcSetKey 1495 if err := decodeHtlcSetKey(r, &htlcSetKey); err != nil { 1496 return nil, err 1497 } 1498 1499 htlcs, err := channeldb.DeserializeHtlcs(r) 1500 if err != nil { 1501 return nil, err 1502 } 1503 1504 c.HtlcSets[htlcSetKey] = htlcs 1505 } 1506 1507 return c, nil 1508 }