/ channeldb / migration24 / migration.go
migration.go
  1  package migration24
  2  
  3  import (
  4  	"bytes"
  5  	"encoding/binary"
  6  	"io"
  7  
  8  	mig "github.com/lightningnetwork/lnd/channeldb/migration_01_to_11"
  9  	"github.com/lightningnetwork/lnd/kvdb"
 10  )
 11  
 12  var (
 13  	// closedChannelBucket stores summarization information concerning
 14  	// previously open, but now closed channels.
 15  	closedChannelBucket = []byte("closed-chan-bucket")
 16  
 17  	// fwdPackagesKey is the root-level bucket that all forwarding packages
 18  	// are written. This bucket is further subdivided based on the short
 19  	// channel ID of each channel.
 20  	fwdPackagesKey = []byte("fwd-packages")
 21  )
 22  
 23  // MigrateFwdPkgCleanup deletes all the forwarding packages of closed channels.
 24  // It determines the closed channels by iterating closedChannelBucket. The
 25  // ShortChanID found in the ChannelCloseSummary is then used as a key to query
 26  // the forwarding packages bucket. If a match is found, it will be deleted.
 27  func MigrateFwdPkgCleanup(tx kvdb.RwTx) error {
 28  	log.Infof("Deleting forwarding packages for closed channels")
 29  
 30  	// Find all closed channel summaries, which are stored in the
 31  	// closeBucket.
 32  	closeBucket := tx.ReadBucket(closedChannelBucket)
 33  	if closeBucket == nil {
 34  		return nil
 35  	}
 36  
 37  	var chanSummaries []*mig.ChannelCloseSummary
 38  
 39  	// appendSummary is a function closure to help put deserialized close
 40  	// summeries into chanSummaries.
 41  	appendSummary := func(_ []byte, summaryBytes []byte) error {
 42  		summaryReader := bytes.NewReader(summaryBytes)
 43  		chanSummary, err := deserializeCloseChannelSummary(
 44  			summaryReader,
 45  		)
 46  		if err != nil {
 47  			return err
 48  		}
 49  
 50  		// Skip pending channels
 51  		if chanSummary.IsPending {
 52  			return nil
 53  		}
 54  
 55  		chanSummaries = append(chanSummaries, chanSummary)
 56  		return nil
 57  	}
 58  
 59  	if err := closeBucket.ForEach(appendSummary); err != nil {
 60  		return err
 61  	}
 62  
 63  	// Now we will load the forwarding packages bucket, delete all the
 64  	// nested buckets whose source matches the ShortChanID found in the
 65  	// closed channel summeraries.
 66  	fwdPkgBkt := tx.ReadWriteBucket(fwdPackagesKey)
 67  	if fwdPkgBkt == nil {
 68  		return nil
 69  	}
 70  
 71  	// Iterate over all close channels and remove their forwarding packages.
 72  	for _, summery := range chanSummaries {
 73  		sourceBytes := MakeLogKey(summery.ShortChanID.ToUint64())
 74  
 75  		// First, we will try to find the corresponding bucket. If there
 76  		// is not a nested bucket matching the ShortChanID, we will skip
 77  		// it.
 78  		if fwdPkgBkt.NestedReadBucket(sourceBytes[:]) == nil {
 79  			continue
 80  		}
 81  
 82  		// Otherwise, wipe all the forwarding packages.
 83  		if err := fwdPkgBkt.DeleteNestedBucket(
 84  			sourceBytes[:],
 85  		); err != nil {
 86  			return err
 87  		}
 88  	}
 89  
 90  	log.Infof("Deletion of forwarding packages of closed channels " +
 91  		"complete! DB compaction is recommended to free up the" +
 92  		"disk space.")
 93  	return nil
 94  }
 95  
 96  // deserializeCloseChannelSummary will decode a CloseChannelSummary with no
 97  // optional fields.
 98  func deserializeCloseChannelSummary(
 99  	r io.Reader) (*mig.ChannelCloseSummary, error) {
100  
101  	c := &mig.ChannelCloseSummary{}
102  	err := mig.ReadElements(
103  		r,
104  		&c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID,
105  		&c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance,
106  		&c.TimeLockedBalance, &c.CloseType, &c.IsPending,
107  	)
108  	if err != nil {
109  		return nil, err
110  	}
111  	return c, nil
112  }
113  
114  // makeLogKey converts a uint64 into an 8 byte array.
115  func MakeLogKey(updateNum uint64) [8]byte {
116  	var key [8]byte
117  	binary.BigEndian.PutUint64(key[:], updateNum)
118  	return key
119  }