github.com/decred/dcrlnd@v0.7.6/channeldb/migration24/migration.go (about)

     1  package migration24
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"io"
     7  
     8  	mig "github.com/decred/dcrlnd/channeldb/migration_01_to_11"
     9  	"github.com/decred/dcrlnd/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[:]); err != nil {
    85  
    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  }