github.com/decred/dcrlnd@v0.7.6/channeldb/forwarding_package.go (about) 1 package channeldb 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 "io" 9 10 "github.com/decred/dcrlnd/kvdb" 11 "github.com/decred/dcrlnd/lnwire" 12 ) 13 14 // ErrCorruptedFwdPkg signals that the on-disk structure of the forwarding 15 // package has potentially been mangled. 16 var ErrCorruptedFwdPkg = errors.New("fwding package db has been corrupted") 17 18 // FwdState is an enum used to describe the lifecycle of a FwdPkg. 19 type FwdState byte 20 21 const ( 22 // FwdStateLockedIn is the starting state for all forwarding packages. 23 // Packages in this state have not yet committed to the exact set of 24 // Adds to forward to the switch. 25 FwdStateLockedIn FwdState = iota 26 27 // FwdStateProcessed marks the state in which all Adds have been 28 // locally processed and the forwarding decision to the switch has been 29 // persisted. 30 FwdStateProcessed 31 32 // FwdStateCompleted signals that all Adds have been acked, and that all 33 // settles and fails have been delivered to their sources. Packages in 34 // this state can be removed permanently. 35 FwdStateCompleted 36 ) 37 38 var ( 39 // fwdPackagesKey is the root-level bucket that all forwarding packages 40 // are written. This bucket is further subdivided based on the short 41 // channel ID of each channel. 42 // 43 // Bucket hierarchy: 44 // 45 // fwdPackagesKey(root-bucket) 46 // | 47 // |-- <shortChannelID> 48 // | | 49 // | |-- <height> 50 // | | |-- ackFilterKey: <encoded bytes of PkgFilter> 51 // | | |-- settleFailFilterKey: <encoded bytes of PkgFilter> 52 // | | |-- fwdFilterKey: <encoded bytes of PkgFilter> 53 // | | | 54 // | | |-- addBucketKey 55 // | | | |-- <index of LogUpdate>: <encoded bytes of LogUpdate> 56 // | | | |-- <index of LogUpdate>: <encoded bytes of LogUpdate> 57 // | | | ... 58 // | | | 59 // | | |-- failSettleBucketKey 60 // | | |-- <index of LogUpdate>: <encoded bytes of LogUpdate> 61 // | | |-- <index of LogUpdate>: <encoded bytes of LogUpdate> 62 // | | ... 63 // | | 64 // | |-- <height> 65 // | | | 66 // | ... ... 67 // | 68 // | 69 // |-- <shortChannelID> 70 // | | 71 // | ... 72 // ... 73 // 74 fwdPackagesKey = []byte("fwd-packages") 75 76 // addBucketKey is the bucket to which all Add log updates are written. 77 addBucketKey = []byte("add-updates") 78 79 // failSettleBucketKey is the bucket to which all Settle/Fail log 80 // updates are written. 81 failSettleBucketKey = []byte("fail-settle-updates") 82 83 // fwdFilterKey is a key used to write the set of Adds that passed 84 // validation and are to be forwarded to the switch. 85 // NOTE: The presence of this key within a forwarding package indicates 86 // that the package has reached FwdStateProcessed. 87 fwdFilterKey = []byte("fwd-filter-key") 88 89 // ackFilterKey is a key used to access the PkgFilter indicating which 90 // Adds have received a Settle/Fail. This response may come from a 91 // number of sources, including: exitHop settle/fails, switch failures, 92 // chain arbiter interjections, as well as settle/fails from the 93 // next hop in the route. 94 ackFilterKey = []byte("ack-filter-key") 95 96 // settleFailFilterKey is a key used to access the PkgFilter indicating 97 // which Settles/Fails in have been received and processed by the link 98 // that originally received the Add. 99 settleFailFilterKey = []byte("settle-fail-filter-key") 100 ) 101 102 // PkgFilter is used to compactly represent a particular subset of the Adds in a 103 // forwarding package. Each filter is represented as a simple, statically-sized 104 // bitvector, where the elements are intended to be the indices of the Adds as 105 // they are written in the FwdPkg. 106 type PkgFilter struct { 107 count uint16 108 filter []byte 109 } 110 111 // NewPkgFilter initializes an empty PkgFilter supporting `count` elements. 112 func NewPkgFilter(count uint16) *PkgFilter { 113 // We add 7 to ensure that the integer division yields properly rounded 114 // values. 115 filterLen := (count + 7) / 8 116 117 return &PkgFilter{ 118 count: count, 119 filter: make([]byte, filterLen), 120 } 121 } 122 123 // Count returns the number of elements represented by this PkgFilter. 124 func (f *PkgFilter) Count() uint16 { 125 return f.count 126 } 127 128 // Set marks the `i`-th element as included by this filter. 129 // NOTE: It is assumed that i is always less than count. 130 func (f *PkgFilter) Set(i uint16) { 131 byt := i / 8 132 bit := i % 8 133 134 // Set the i-th bit in the filter. 135 // TODO(conner): ignore if > count to prevent panic? 136 f.filter[byt] |= byte(1 << (7 - bit)) 137 } 138 139 // Contains queries the filter for membership of index `i`. 140 // NOTE: It is assumed that i is always less than count. 141 func (f *PkgFilter) Contains(i uint16) bool { 142 byt := i / 8 143 bit := i % 8 144 145 // Read the i-th bit in the filter. 146 // TODO(conner): ignore if > count to prevent panic? 147 return f.filter[byt]&(1<<(7-bit)) != 0 148 } 149 150 // Equal checks two PkgFilters for equality. 151 func (f *PkgFilter) Equal(f2 *PkgFilter) bool { 152 if f == f2 { 153 return true 154 } 155 if f.count != f2.count { 156 return false 157 } 158 159 return bytes.Equal(f.filter, f2.filter) 160 } 161 162 // IsFull returns true if every element in the filter has been Set, and false 163 // otherwise. 164 func (f *PkgFilter) IsFull() bool { 165 // Batch validate bytes that are fully used. 166 for i := uint16(0); i < f.count/8; i++ { 167 if f.filter[i] != 0xFF { 168 return false 169 } 170 } 171 172 // If the count is not a multiple of 8, check that the filter contains 173 // all remaining bits. 174 rem := f.count % 8 175 for idx := f.count - rem; idx < f.count; idx++ { 176 if !f.Contains(idx) { 177 return false 178 } 179 } 180 181 return true 182 } 183 184 // Size returns number of bytes produced when the PkgFilter is serialized. 185 func (f *PkgFilter) Size() uint16 { 186 // 2 bytes for uint16 `count`, then round up number of bytes required to 187 // represent `count` bits. 188 return 2 + (f.count+7)/8 189 } 190 191 // Encode writes the filter to the provided io.Writer. 192 func (f *PkgFilter) Encode(w io.Writer) error { 193 if err := binary.Write(w, binary.BigEndian, f.count); err != nil { 194 return err 195 } 196 197 _, err := w.Write(f.filter) 198 199 return err 200 } 201 202 // Decode reads the filter from the provided io.Reader. 203 func (f *PkgFilter) Decode(r io.Reader) error { 204 if err := binary.Read(r, binary.BigEndian, &f.count); err != nil { 205 return err 206 } 207 208 f.filter = make([]byte, f.Size()-2) 209 _, err := io.ReadFull(r, f.filter) 210 211 return err 212 } 213 214 // FwdPkg records all adds, settles, and fails that were locked in as a result 215 // of the remote peer sending us a revocation. Each package is identified by 216 // the short chanid and remote commitment height corresponding to the revocation 217 // that locked in the HTLCs. For everything except a locally initiated payment, 218 // settles and fails in a forwarding package must have a corresponding Add in 219 // another package, and can be removed individually once the source link has 220 // received the fail/settle. 221 // 222 // Adds cannot be removed, as we need to present the same batch of Adds to 223 // properly handle replay protection. Instead, we use a PkgFilter to mark that 224 // we have finished processing a particular Add. A FwdPkg should only be deleted 225 // after the AckFilter is full and all settles and fails have been persistently 226 // removed. 227 type FwdPkg struct { 228 // Source identifies the channel that wrote this forwarding package. 229 Source lnwire.ShortChannelID 230 231 // Height is the height of the remote commitment chain that locked in 232 // this forwarding package. 233 Height uint64 234 235 // State signals the persistent condition of the package and directs how 236 // to reprocess the package in the event of failures. 237 State FwdState 238 239 // Adds contains all add messages which need to be processed and 240 // forwarded to the switch. Adds does not change over the life of a 241 // forwarding package. 242 Adds []LogUpdate 243 244 // FwdFilter is a filter containing the indices of all Adds that were 245 // forwarded to the switch. 246 FwdFilter *PkgFilter 247 248 // AckFilter is a filter containing the indices of all Adds for which 249 // the source has received a settle or fail and is reflected in the next 250 // commitment txn. A package should not be removed until IsFull() 251 // returns true. 252 AckFilter *PkgFilter 253 254 // SettleFails contains all settle and fail messages that should be 255 // forwarded to the switch. 256 SettleFails []LogUpdate 257 258 // SettleFailFilter is a filter containing the indices of all Settle or 259 // Fails originating in this package that have been received and locked 260 // into the incoming link's commitment state. 261 SettleFailFilter *PkgFilter 262 } 263 264 // NewFwdPkg initializes a new forwarding package in FwdStateLockedIn. This 265 // should be used to create a package at the time we receive a revocation. 266 func NewFwdPkg(source lnwire.ShortChannelID, height uint64, 267 addUpdates, settleFailUpdates []LogUpdate) *FwdPkg { 268 269 nAddUpdates := uint16(len(addUpdates)) 270 nSettleFailUpdates := uint16(len(settleFailUpdates)) 271 272 return &FwdPkg{ 273 Source: source, 274 Height: height, 275 State: FwdStateLockedIn, 276 Adds: addUpdates, 277 FwdFilter: NewPkgFilter(nAddUpdates), 278 AckFilter: NewPkgFilter(nAddUpdates), 279 SettleFails: settleFailUpdates, 280 SettleFailFilter: NewPkgFilter(nSettleFailUpdates), 281 } 282 } 283 284 // ID returns an unique identifier for this package, used to ensure that sphinx 285 // replay processing of this batch is idempotent. 286 func (f *FwdPkg) ID() []byte { 287 var id = make([]byte, 16) 288 byteOrder.PutUint64(id[:8], f.Source.ToUint64()) 289 byteOrder.PutUint64(id[8:], f.Height) 290 return id 291 } 292 293 // String returns a human-readable description of the forwarding package. 294 func (f *FwdPkg) String() string { 295 return fmt.Sprintf("%T(src=%v, height=%v, nadds=%v, nfailsettles=%v)", 296 f, f.Source, f.Height, len(f.Adds), len(f.SettleFails)) 297 } 298 299 // AddRef is used to identify a particular Add in a FwdPkg. The short channel ID 300 // is assumed to be that of the packager. 301 type AddRef struct { 302 // Height is the remote commitment height that locked in the Add. 303 Height uint64 304 305 // Index is the index of the Add within the fwd pkg's Adds. 306 // 307 // NOTE: This index is static over the lifetime of a forwarding package. 308 Index uint16 309 } 310 311 // Encode serializes the AddRef to the given io.Writer. 312 func (a *AddRef) Encode(w io.Writer) error { 313 if err := binary.Write(w, binary.BigEndian, a.Height); err != nil { 314 return err 315 } 316 317 return binary.Write(w, binary.BigEndian, a.Index) 318 } 319 320 // Decode deserializes the AddRef from the given io.Reader. 321 func (a *AddRef) Decode(r io.Reader) error { 322 if err := binary.Read(r, binary.BigEndian, &a.Height); err != nil { 323 return err 324 } 325 326 return binary.Read(r, binary.BigEndian, &a.Index) 327 } 328 329 // SettleFailRef is used to locate a Settle/Fail in another channel's FwdPkg. A 330 // channel does not remove its own Settle/Fail htlcs, so the source is provided 331 // to locate a db bucket belonging to another channel. 332 type SettleFailRef struct { 333 // Source identifies the outgoing link that locked in the settle or 334 // fail. This is then used by the *incoming* link to find the settle 335 // fail in another link's forwarding packages. 336 Source lnwire.ShortChannelID 337 338 // Height is the remote commitment height that locked in this 339 // Settle/Fail. 340 Height uint64 341 342 // Index is the index of the Add with the fwd pkg's SettleFails. 343 // 344 // NOTE: This index is static over the lifetime of a forwarding package. 345 Index uint16 346 } 347 348 // SettleFailAcker is a generic interface providing the ability to acknowledge 349 // settle/fail HTLCs stored in forwarding packages. 350 type SettleFailAcker interface { 351 // AckSettleFails atomically updates the settle-fail filters in *other* 352 // channels' forwarding packages. 353 AckSettleFails(tx kvdb.RwTx, settleFailRefs ...SettleFailRef) error 354 } 355 356 // GlobalFwdPkgReader is an interface used to retrieve the forwarding packages 357 // of any active channel. 358 type GlobalFwdPkgReader interface { 359 // LoadChannelFwdPkgs loads all known forwarding packages for the given 360 // channel. 361 LoadChannelFwdPkgs(tx kvdb.RTx, 362 source lnwire.ShortChannelID) ([]*FwdPkg, error) 363 } 364 365 // FwdOperator defines the interfaces for managing forwarding packages that are 366 // external to a particular channel. This interface is used by the switch to 367 // read forwarding packages from arbitrary channels, and acknowledge settles and 368 // fails for locally-sourced payments. 369 type FwdOperator interface { 370 // GlobalFwdPkgReader provides read access to all known forwarding 371 // packages 372 GlobalFwdPkgReader 373 374 // SettleFailAcker grants the ability to acknowledge settles or fails 375 // residing in arbitrary forwarding packages. 376 SettleFailAcker 377 } 378 379 // SwitchPackager is a concrete implementation of the FwdOperator interface. 380 // A SwitchPackager offers the ability to read any forwarding package, and ack 381 // arbitrary settle and fail HTLCs. 382 type SwitchPackager struct{} 383 384 // NewSwitchPackager instantiates a new SwitchPackager. 385 func NewSwitchPackager() *SwitchPackager { 386 return &SwitchPackager{} 387 } 388 389 // AckSettleFails atomically updates the settle-fail filters in *other* 390 // channels' forwarding packages, to mark that the switch has received a settle 391 // or fail residing in the forwarding package of a link. 392 func (*SwitchPackager) AckSettleFails(tx kvdb.RwTx, 393 settleFailRefs ...SettleFailRef) error { 394 395 return ackSettleFails(tx, settleFailRefs) 396 } 397 398 // LoadChannelFwdPkgs loads all forwarding packages for a particular channel. 399 func (*SwitchPackager) LoadChannelFwdPkgs(tx kvdb.RTx, 400 source lnwire.ShortChannelID) ([]*FwdPkg, error) { 401 402 return loadChannelFwdPkgs(tx, source) 403 } 404 405 // FwdPackager supports all operations required to modify fwd packages, such as 406 // creation, updates, reading, and removal. The interfaces are broken down in 407 // this way to support future delegation of the subinterfaces. 408 type FwdPackager interface { 409 // AddFwdPkg serializes and writes a FwdPkg for this channel at the 410 // remote commitment height included in the forwarding package. 411 AddFwdPkg(tx kvdb.RwTx, fwdPkg *FwdPkg) error 412 413 // SetFwdFilter looks up the forwarding package at the remote `height` 414 // and sets the `fwdFilter`, marking the Adds for which: 415 // 1) We are not the exit node 416 // 2) Passed all validation 417 // 3) Should be forwarded to the switch immediately after a failure 418 SetFwdFilter(tx kvdb.RwTx, height uint64, fwdFilter *PkgFilter) error 419 420 // AckAddHtlcs atomically updates the add filters in this channel's 421 // forwarding packages to mark the resolution of an Add that was 422 // received from the remote party. 423 AckAddHtlcs(tx kvdb.RwTx, addRefs ...AddRef) error 424 425 // SettleFailAcker allows a link to acknowledge settle/fail HTLCs 426 // belonging to other channels. 427 SettleFailAcker 428 429 // LoadFwdPkgs loads all known forwarding packages owned by this 430 // channel. 431 LoadFwdPkgs(tx kvdb.RTx) ([]*FwdPkg, error) 432 433 // RemovePkg deletes a forwarding package owned by this channel at 434 // the provided remote `height`. 435 RemovePkg(tx kvdb.RwTx, height uint64) error 436 437 // Wipe deletes all the forwarding packages owned by this channel. 438 Wipe(tx kvdb.RwTx) error 439 } 440 441 // ChannelPackager is used by a channel to manage the lifecycle of its forwarding 442 // packages. The packager is tied to a particular source channel ID, allowing it 443 // to create and edit its own packages. Each packager also has the ability to 444 // remove fail/settle htlcs that correspond to an add contained in one of 445 // source's packages. 446 type ChannelPackager struct { 447 source lnwire.ShortChannelID 448 } 449 450 // NewChannelPackager creates a new packager for a single channel. 451 func NewChannelPackager(source lnwire.ShortChannelID) *ChannelPackager { 452 return &ChannelPackager{ 453 source: source, 454 } 455 } 456 457 // AddFwdPkg writes a newly locked in forwarding package to disk. 458 func (*ChannelPackager) AddFwdPkg(tx kvdb.RwTx, fwdPkg *FwdPkg) error { 459 fwdPkgBkt, err := tx.CreateTopLevelBucket(fwdPackagesKey) 460 if err != nil { 461 return err 462 } 463 464 source := makeLogKey(fwdPkg.Source.ToUint64()) 465 sourceBkt, err := fwdPkgBkt.CreateBucketIfNotExists(source[:]) 466 if err != nil { 467 return err 468 } 469 470 heightKey := makeLogKey(fwdPkg.Height) 471 heightBkt, err := sourceBkt.CreateBucketIfNotExists(heightKey[:]) 472 if err != nil { 473 return err 474 } 475 476 // Write ADD updates we received at this commit height. 477 addBkt, err := heightBkt.CreateBucketIfNotExists(addBucketKey) 478 if err != nil { 479 return err 480 } 481 482 // Write SETTLE/FAIL updates we received at this commit height. 483 failSettleBkt, err := heightBkt.CreateBucketIfNotExists(failSettleBucketKey) 484 if err != nil { 485 return err 486 } 487 488 for i := range fwdPkg.Adds { 489 err = putLogUpdate(addBkt, uint16(i), &fwdPkg.Adds[i]) 490 if err != nil { 491 return err 492 } 493 } 494 495 // Persist the initialized pkg filter, which will be used to determine 496 // when we can remove this forwarding package from disk. 497 var ackFilterBuf bytes.Buffer 498 if err := fwdPkg.AckFilter.Encode(&ackFilterBuf); err != nil { 499 return err 500 } 501 502 if err := heightBkt.Put(ackFilterKey, ackFilterBuf.Bytes()); err != nil { 503 return err 504 } 505 506 for i := range fwdPkg.SettleFails { 507 err = putLogUpdate(failSettleBkt, uint16(i), &fwdPkg.SettleFails[i]) 508 if err != nil { 509 return err 510 } 511 } 512 513 var settleFailFilterBuf bytes.Buffer 514 err = fwdPkg.SettleFailFilter.Encode(&settleFailFilterBuf) 515 if err != nil { 516 return err 517 } 518 519 return heightBkt.Put(settleFailFilterKey, settleFailFilterBuf.Bytes()) 520 } 521 522 // putLogUpdate writes an htlc to the provided `bkt`, using `index` as the key. 523 func putLogUpdate(bkt kvdb.RwBucket, idx uint16, htlc *LogUpdate) error { 524 var b bytes.Buffer 525 if err := serializeLogUpdate(&b, htlc); err != nil { 526 return err 527 } 528 529 return bkt.Put(uint16Key(idx), b.Bytes()) 530 } 531 532 // LoadFwdPkgs scans the forwarding log for any packages that haven't been 533 // processed, and returns their deserialized log updates in a map indexed by the 534 // remote commitment height at which the updates were locked in. 535 func (p *ChannelPackager) LoadFwdPkgs(tx kvdb.RTx) ([]*FwdPkg, error) { 536 return loadChannelFwdPkgs(tx, p.source) 537 } 538 539 // loadChannelFwdPkgs loads all forwarding packages owned by `source`. 540 func loadChannelFwdPkgs(tx kvdb.RTx, source lnwire.ShortChannelID) ([]*FwdPkg, error) { 541 fwdPkgBkt := tx.ReadBucket(fwdPackagesKey) 542 if fwdPkgBkt == nil { 543 return nil, nil 544 } 545 546 sourceKey := makeLogKey(source.ToUint64()) 547 sourceBkt := fwdPkgBkt.NestedReadBucket(sourceKey[:]) 548 if sourceBkt == nil { 549 return nil, nil 550 } 551 552 var heights []uint64 553 if err := sourceBkt.ForEach(func(k, _ []byte) error { 554 if len(k) != 8 { 555 return ErrCorruptedFwdPkg 556 } 557 558 heights = append(heights, byteOrder.Uint64(k)) 559 560 return nil 561 }); err != nil { 562 return nil, err 563 } 564 565 // Load the forwarding package for each retrieved height. 566 fwdPkgs := make([]*FwdPkg, 0, len(heights)) 567 for _, height := range heights { 568 fwdPkg, err := loadFwdPkg(fwdPkgBkt, source, height) 569 if err != nil { 570 return nil, err 571 } 572 573 fwdPkgs = append(fwdPkgs, fwdPkg) 574 } 575 576 return fwdPkgs, nil 577 } 578 579 // loadFwdPkg reads the packager's fwd pkg at a given height, and determines the 580 // appropriate FwdState. 581 func loadFwdPkg(fwdPkgBkt kvdb.RBucket, source lnwire.ShortChannelID, 582 height uint64) (*FwdPkg, error) { 583 584 sourceKey := makeLogKey(source.ToUint64()) 585 sourceBkt := fwdPkgBkt.NestedReadBucket(sourceKey[:]) 586 if sourceBkt == nil { 587 return nil, ErrCorruptedFwdPkg 588 } 589 590 heightKey := makeLogKey(height) 591 heightBkt := sourceBkt.NestedReadBucket(heightKey[:]) 592 if heightBkt == nil { 593 return nil, ErrCorruptedFwdPkg 594 } 595 596 // Load ADDs from disk. 597 addBkt := heightBkt.NestedReadBucket(addBucketKey) 598 if addBkt == nil { 599 return nil, ErrCorruptedFwdPkg 600 } 601 602 adds, err := loadHtlcs(addBkt) 603 if err != nil { 604 return nil, err 605 } 606 607 // Load ack filter from disk. 608 ackFilterBytes := heightBkt.Get(ackFilterKey) 609 if ackFilterBytes == nil { 610 return nil, ErrCorruptedFwdPkg 611 } 612 ackFilterReader := bytes.NewReader(ackFilterBytes) 613 614 ackFilter := &PkgFilter{} 615 if err := ackFilter.Decode(ackFilterReader); err != nil { 616 return nil, err 617 } 618 619 // Load SETTLE/FAILs from disk. 620 failSettleBkt := heightBkt.NestedReadBucket(failSettleBucketKey) 621 if failSettleBkt == nil { 622 return nil, ErrCorruptedFwdPkg 623 } 624 625 failSettles, err := loadHtlcs(failSettleBkt) 626 if err != nil { 627 return nil, err 628 } 629 630 // Load settle fail filter from disk. 631 settleFailFilterBytes := heightBkt.Get(settleFailFilterKey) 632 if settleFailFilterBytes == nil { 633 return nil, ErrCorruptedFwdPkg 634 } 635 settleFailFilterReader := bytes.NewReader(settleFailFilterBytes) 636 637 settleFailFilter := &PkgFilter{} 638 if err := settleFailFilter.Decode(settleFailFilterReader); err != nil { 639 return nil, err 640 } 641 642 // Initialize the fwding package, which always starts in the 643 // FwdStateLockedIn. We can determine what state the package was left in 644 // by examining constraints on the information loaded from disk. 645 fwdPkg := &FwdPkg{ 646 Source: source, 647 State: FwdStateLockedIn, 648 Height: height, 649 Adds: adds, 650 AckFilter: ackFilter, 651 SettleFails: failSettles, 652 SettleFailFilter: settleFailFilter, 653 } 654 655 // Check to see if we have written the set exported filter adds to 656 // disk. If we haven't, processing of this package was never started, or 657 // failed during the last attempt. 658 fwdFilterBytes := heightBkt.Get(fwdFilterKey) 659 if fwdFilterBytes == nil { 660 nAdds := uint16(len(adds)) 661 fwdPkg.FwdFilter = NewPkgFilter(nAdds) 662 return fwdPkg, nil 663 } 664 665 fwdFilterReader := bytes.NewReader(fwdFilterBytes) 666 fwdPkg.FwdFilter = &PkgFilter{} 667 if err := fwdPkg.FwdFilter.Decode(fwdFilterReader); err != nil { 668 return nil, err 669 } 670 671 // Otherwise, a complete round of processing was completed, and we 672 // advance the package to FwdStateProcessed. 673 fwdPkg.State = FwdStateProcessed 674 675 // If every add, settle, and fail has been fully acknowledged, we can 676 // safely set the package's state to FwdStateCompleted, signalling that 677 // it can be garbage collected. 678 if fwdPkg.AckFilter.IsFull() && fwdPkg.SettleFailFilter.IsFull() { 679 fwdPkg.State = FwdStateCompleted 680 } 681 682 return fwdPkg, nil 683 } 684 685 // loadHtlcs retrieves all serialized htlcs in a bucket, returning 686 // them in order of the indexes they were written under. 687 func loadHtlcs(bkt kvdb.RBucket) ([]LogUpdate, error) { 688 var htlcs []LogUpdate 689 if err := bkt.ForEach(func(_, v []byte) error { 690 htlc, err := deserializeLogUpdate(bytes.NewReader(v)) 691 if err != nil { 692 return err 693 } 694 695 htlcs = append(htlcs, *htlc) 696 697 return nil 698 }); err != nil { 699 return nil, err 700 } 701 702 return htlcs, nil 703 } 704 705 // SetFwdFilter writes the set of indexes corresponding to Adds at the 706 // `height` that are to be forwarded to the switch. Calling this method causes 707 // the forwarding package at `height` to be in FwdStateProcessed. We write this 708 // forwarding decision so that we always arrive at the same behavior for HTLCs 709 // leaving this channel. After a restart, we skip validation of these Adds, 710 // since they are assumed to have already been validated, and make the switch or 711 // outgoing link responsible for handling replays. 712 func (p *ChannelPackager) SetFwdFilter(tx kvdb.RwTx, height uint64, 713 fwdFilter *PkgFilter) error { 714 715 fwdPkgBkt := tx.ReadWriteBucket(fwdPackagesKey) 716 if fwdPkgBkt == nil { 717 return ErrCorruptedFwdPkg 718 } 719 720 source := makeLogKey(p.source.ToUint64()) 721 sourceBkt := fwdPkgBkt.NestedReadWriteBucket(source[:]) 722 if sourceBkt == nil { 723 return ErrCorruptedFwdPkg 724 } 725 726 heightKey := makeLogKey(height) 727 heightBkt := sourceBkt.NestedReadWriteBucket(heightKey[:]) 728 if heightBkt == nil { 729 return ErrCorruptedFwdPkg 730 } 731 732 // If the fwd filter has already been written, we return early to avoid 733 // modifying the persistent state. 734 forwardedAddsBytes := heightBkt.Get(fwdFilterKey) 735 if forwardedAddsBytes != nil { 736 return nil 737 } 738 739 // Otherwise we serialize and write the provided fwd filter. 740 var b bytes.Buffer 741 if err := fwdFilter.Encode(&b); err != nil { 742 return err 743 } 744 745 return heightBkt.Put(fwdFilterKey, b.Bytes()) 746 } 747 748 // AckAddHtlcs accepts a list of references to add htlcs, and updates the 749 // AckAddFilter of those forwarding packages to indicate that a settle or fail 750 // has been received in response to the add. 751 func (p *ChannelPackager) AckAddHtlcs(tx kvdb.RwTx, addRefs ...AddRef) error { 752 if len(addRefs) == 0 { 753 return nil 754 } 755 756 fwdPkgBkt := tx.ReadWriteBucket(fwdPackagesKey) 757 if fwdPkgBkt == nil { 758 return ErrCorruptedFwdPkg 759 } 760 761 sourceKey := makeLogKey(p.source.ToUint64()) 762 sourceBkt := fwdPkgBkt.NestedReadWriteBucket(sourceKey[:]) 763 if sourceBkt == nil { 764 return ErrCorruptedFwdPkg 765 } 766 767 // Organize the forward references such that we just get a single slice 768 // of indexes for each unique height. 769 heightDiffs := make(map[uint64][]uint16) 770 for _, addRef := range addRefs { 771 heightDiffs[addRef.Height] = append( 772 heightDiffs[addRef.Height], 773 addRef.Index, 774 ) 775 } 776 777 // Load each height bucket once and remove all acked htlcs at that 778 // height. 779 for height, indexes := range heightDiffs { 780 err := ackAddHtlcsAtHeight(sourceBkt, height, indexes) 781 if err != nil { 782 return err 783 } 784 } 785 786 return nil 787 } 788 789 // ackAddHtlcsAtHeight updates the AddAckFilter of a single forwarding package 790 // with a list of indexes, writing the resulting filter back in its place. 791 func ackAddHtlcsAtHeight(sourceBkt kvdb.RwBucket, height uint64, 792 indexes []uint16) error { 793 794 heightKey := makeLogKey(height) 795 heightBkt := sourceBkt.NestedReadWriteBucket(heightKey[:]) 796 if heightBkt == nil { 797 // If the height bucket isn't found, this could be because the 798 // forwarding package was already removed. We'll return nil to 799 // signal that the operation is successful, as there is nothing 800 // to ack. 801 return nil 802 } 803 804 // Load ack filter from disk. 805 ackFilterBytes := heightBkt.Get(ackFilterKey) 806 if ackFilterBytes == nil { 807 return ErrCorruptedFwdPkg 808 } 809 810 ackFilter := &PkgFilter{} 811 ackFilterReader := bytes.NewReader(ackFilterBytes) 812 if err := ackFilter.Decode(ackFilterReader); err != nil { 813 return err 814 } 815 816 // Update the ack filter for this height. 817 for _, index := range indexes { 818 ackFilter.Set(index) 819 } 820 821 // Write the resulting filter to disk. 822 var ackFilterBuf bytes.Buffer 823 if err := ackFilter.Encode(&ackFilterBuf); err != nil { 824 return err 825 } 826 827 return heightBkt.Put(ackFilterKey, ackFilterBuf.Bytes()) 828 } 829 830 // AckSettleFails persistently acknowledges settles or fails from a remote forwarding 831 // package. This should only be called after the source of the Add has locked in 832 // the settle/fail, or it becomes otherwise safe to forgo retransmitting the 833 // settle/fail after a restart. 834 func (p *ChannelPackager) AckSettleFails(tx kvdb.RwTx, settleFailRefs ...SettleFailRef) error { 835 return ackSettleFails(tx, settleFailRefs) 836 } 837 838 // ackSettleFails persistently acknowledges a batch of settle fail references. 839 func ackSettleFails(tx kvdb.RwTx, settleFailRefs []SettleFailRef) error { 840 if len(settleFailRefs) == 0 { 841 return nil 842 } 843 844 fwdPkgBkt := tx.ReadWriteBucket(fwdPackagesKey) 845 if fwdPkgBkt == nil { 846 return ErrCorruptedFwdPkg 847 } 848 849 // Organize the forward references such that we just get a single slice 850 // of indexes for each unique destination-height pair. 851 destHeightDiffs := make(map[lnwire.ShortChannelID]map[uint64][]uint16) 852 for _, settleFailRef := range settleFailRefs { 853 destHeights, ok := destHeightDiffs[settleFailRef.Source] 854 if !ok { 855 destHeights = make(map[uint64][]uint16) 856 destHeightDiffs[settleFailRef.Source] = destHeights 857 } 858 859 destHeights[settleFailRef.Height] = append( 860 destHeights[settleFailRef.Height], 861 settleFailRef.Index, 862 ) 863 } 864 865 // With the references organized by destination and height, we now load 866 // each remote bucket, and update the settle fail filter for any 867 // settle/fail htlcs. 868 for dest, destHeights := range destHeightDiffs { 869 destKey := makeLogKey(dest.ToUint64()) 870 destBkt := fwdPkgBkt.NestedReadWriteBucket(destKey[:]) 871 if destBkt == nil { 872 // If the destination bucket is not found, this is 873 // likely the result of the destination channel being 874 // closed and having it's forwarding packages wiped. We 875 // won't treat this as an error, because the response 876 // will no longer be retransmitted internally. 877 continue 878 } 879 880 for height, indexes := range destHeights { 881 err := ackSettleFailsAtHeight(destBkt, height, indexes) 882 if err != nil { 883 return err 884 } 885 } 886 } 887 888 return nil 889 } 890 891 // ackSettleFailsAtHeight given a destination bucket, acks the provided indexes 892 // at particular a height by updating the settle fail filter. 893 func ackSettleFailsAtHeight(destBkt kvdb.RwBucket, height uint64, 894 indexes []uint16) error { 895 896 heightKey := makeLogKey(height) 897 heightBkt := destBkt.NestedReadWriteBucket(heightKey[:]) 898 if heightBkt == nil { 899 // If the height bucket isn't found, this could be because the 900 // forwarding package was already removed. We'll return nil to 901 // signal that the operation is as there is nothing to ack. 902 return nil 903 } 904 905 // Load ack filter from disk. 906 settleFailFilterBytes := heightBkt.Get(settleFailFilterKey) 907 if settleFailFilterBytes == nil { 908 return ErrCorruptedFwdPkg 909 } 910 911 settleFailFilter := &PkgFilter{} 912 settleFailFilterReader := bytes.NewReader(settleFailFilterBytes) 913 if err := settleFailFilter.Decode(settleFailFilterReader); err != nil { 914 return err 915 } 916 917 // Update the ack filter for this height. 918 for _, index := range indexes { 919 settleFailFilter.Set(index) 920 } 921 922 // Write the resulting filter to disk. 923 var settleFailFilterBuf bytes.Buffer 924 if err := settleFailFilter.Encode(&settleFailFilterBuf); err != nil { 925 return err 926 } 927 928 return heightBkt.Put(settleFailFilterKey, settleFailFilterBuf.Bytes()) 929 } 930 931 // RemovePkg deletes the forwarding package at the given height from the 932 // packager's source bucket. 933 func (p *ChannelPackager) RemovePkg(tx kvdb.RwTx, height uint64) error { 934 fwdPkgBkt := tx.ReadWriteBucket(fwdPackagesKey) 935 if fwdPkgBkt == nil { 936 return nil 937 } 938 939 sourceBytes := makeLogKey(p.source.ToUint64()) 940 sourceBkt := fwdPkgBkt.NestedReadWriteBucket(sourceBytes[:]) 941 if sourceBkt == nil { 942 return ErrCorruptedFwdPkg 943 } 944 945 heightKey := makeLogKey(height) 946 947 return sourceBkt.DeleteNestedBucket(heightKey[:]) 948 } 949 950 // Wipe deletes all the channel's forwarding packages, if any. 951 func (p *ChannelPackager) Wipe(tx kvdb.RwTx) error { 952 // If the root bucket doesn't exist, there's no need to delete. 953 fwdPkgBkt := tx.ReadWriteBucket(fwdPackagesKey) 954 if fwdPkgBkt == nil { 955 return nil 956 } 957 958 sourceBytes := makeLogKey(p.source.ToUint64()) 959 960 // If the nested bucket doesn't exist, there's no need to delete. 961 if fwdPkgBkt.NestedReadWriteBucket(sourceBytes[:]) == nil { 962 return nil 963 } 964 965 return fwdPkgBkt.DeleteNestedBucket(sourceBytes[:]) 966 } 967 968 // uint16Key writes the provided 16-bit unsigned integer to a 2-byte slice. 969 func uint16Key(i uint16) []byte { 970 key := make([]byte, 2) 971 byteOrder.PutUint16(key, i) 972 return key 973 } 974 975 // Compile-time constraint to ensure that ChannelPackager implements the public 976 // FwdPackager interface. 977 var _ FwdPackager = (*ChannelPackager)(nil) 978 979 // Compile-time constraint to ensure that SwitchPackager implements the public 980 // FwdOperator interface. 981 var _ FwdOperator = (*SwitchPackager)(nil)