mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-24 06:47:44 +01:00
In this commit, a new channel-ID index is added to the tower client db with the help of a migration. This index holds a mapping from a db-assigned-ID (a uint64 encoded using BigSize encoding) to real channel ID (32 bytes). This mapping will help us save space in future when persisting references to channels.
104 lines
3.3 KiB
Go
104 lines
3.3 KiB
Go
package migration3
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
|
|
"github.com/lightningnetwork/lnd/kvdb"
|
|
"github.com/lightningnetwork/lnd/tlv"
|
|
)
|
|
|
|
var (
|
|
// cChanDetailsBkt is a top-level bucket storing:
|
|
// channel-id => cChannelSummary -> encoded ClientChanSummary.
|
|
// => cChanDBID -> db-assigned-id
|
|
cChanDetailsBkt = []byte("client-channel-detail-bucket")
|
|
|
|
// cChanDBID is a key used in the cChanDetailsBkt to store the
|
|
// db-assigned-id of a channel.
|
|
cChanDBID = []byte("client-channel-db-id")
|
|
|
|
// cChanIDIndexBkt is a top-level bucket storing:
|
|
// db-assigned-id -> channel-ID
|
|
cChanIDIndexBkt = []byte("client-channel-id-index")
|
|
|
|
// cChannelSummary is a key used in cChanDetailsBkt to store the encoded
|
|
// body of ClientChanSummary.
|
|
cChannelSummary = []byte("client-channel-summary")
|
|
|
|
// ErrUninitializedDB signals that top-level buckets for the database
|
|
// have not been initialized.
|
|
ErrUninitializedDB = errors.New("db not initialized")
|
|
|
|
// ErrCorruptChanDetails signals that the clients channel detail's
|
|
// on-disk structure deviates from what is expected.
|
|
ErrCorruptChanDetails = errors.New("channel details corrupted")
|
|
|
|
byteOrder = binary.BigEndian
|
|
)
|
|
|
|
// MigrateChannelIDIndex adds a new channel ID index to the tower client db.
|
|
// This index is a mapping from db-assigned ID (a uint64 encoded using BigSize
|
|
// encoding) to real channel ID (32 bytes). This mapping will allow us to
|
|
// persist channel pointers with fewer bytes in the future.
|
|
func MigrateChannelIDIndex(tx kvdb.RwTx) error {
|
|
log.Infof("Migrating the tower client db to add a new channel ID " +
|
|
"index which stores a mapping from db-assigned ID to real " +
|
|
"channel ID")
|
|
|
|
// Create a new top-level bucket for the new index.
|
|
indexBkt, err := tx.CreateTopLevelBucket(cChanIDIndexBkt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Get the top-level channel-details bucket. The keys of this bucket
|
|
// are the real channel IDs.
|
|
chanDetailsBkt := tx.ReadWriteBucket(cChanDetailsBkt)
|
|
if chanDetailsBkt == nil {
|
|
return ErrUninitializedDB
|
|
}
|
|
|
|
// Iterate over the keys of the channel-details bucket.
|
|
return chanDetailsBkt.ForEach(func(chanID, _ []byte) error {
|
|
// Ask the db for a new, unique, ID for the index bucket.
|
|
nextSeq, err := indexBkt.NextSequence()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Encode the sequence number using BigSize encoding.
|
|
var newIndex bytes.Buffer
|
|
err = tlv.WriteVarInt(&newIndex, nextSeq, &[8]byte{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Add the mapping from the db-assigned ID to the channel ID
|
|
// to the new index.
|
|
newIndexBytes := newIndex.Bytes()
|
|
err = indexBkt.Put(newIndexBytes, chanID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
chanDetails := chanDetailsBkt.NestedReadWriteBucket(chanID)
|
|
if chanDetails == nil {
|
|
return ErrCorruptChanDetails
|
|
}
|
|
|
|
// Here we ensure that the channel-details bucket includes a
|
|
// channel summary. The only reason we do this is so that we can
|
|
// simulate a migration fail in a test to ensure that a
|
|
// migration fail results in an untouched db.
|
|
chanSummaryBytes := chanDetails.Get(cChannelSummary)
|
|
if chanSummaryBytes == nil {
|
|
return ErrCorruptChanDetails
|
|
}
|
|
|
|
// In the channel-details sub-bucket for this channel, add the
|
|
// new DB-assigned ID for this channel under the cChanDBID key.
|
|
return chanDetails.Put(cChanDBID, newIndexBytes)
|
|
})
|
|
}
|