mirror of
https://github.com/lightninglabs/loop
synced 2024-11-16 00:12:52 +00:00
535e964ec9
A database field was already in place to allow channel selection for loop in. Unfortunately this field, which contains a short channel id, isn't easily usable for controlling the loop server payment. Because of non-strict forwarding, it is only possible to constrain a route to a specific last hop pubkey. This commit converts the existing field into a pubkey field.
87 lines
2.4 KiB
Go
87 lines
2.4 KiB
Go
package loopdb
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg"
|
|
"github.com/coreos/bbolt"
|
|
)
|
|
|
|
// migrateLastHop migrates the database to v03, replacing the never used loop in
|
|
// channel by a last hop pubkey.
|
|
func migrateLastHop(tx *bbolt.Tx, chainParams *chaincfg.Params) error {
|
|
rootBucket := tx.Bucket(loopInBucketKey)
|
|
if rootBucket == nil {
|
|
return errors.New("bucket does not exist")
|
|
}
|
|
|
|
return rootBucket.ForEach(func(swapHash, v []byte) error {
|
|
// Only go into things that we know are sub-bucket
|
|
// keys.
|
|
if v != nil {
|
|
return nil
|
|
}
|
|
|
|
// From the root bucket, we'll grab the next swap
|
|
// bucket for this swap from its swaphash.
|
|
swapBucket := rootBucket.Bucket(swapHash)
|
|
if swapBucket == nil {
|
|
return fmt.Errorf("swap bucket %x not found",
|
|
swapHash)
|
|
}
|
|
|
|
// With the main swap bucket obtained, we'll grab the
|
|
// raw swap contract bytes.
|
|
contractBytes := swapBucket.Get(contractKey)
|
|
if contractBytes == nil {
|
|
return errors.New("contract not found")
|
|
}
|
|
|
|
const (
|
|
// deprecatedLoopInChannelStart is the starting offset
|
|
// of the old loop in channel field: 8 (initiation time)
|
|
// + 32 (preimage) + 8 (amount requested) + 33 + 33
|
|
// (sender and receiver keys) + 4 (cltv expiry) + 8 + 8
|
|
// (max miner and swap fee) + 4 (initiation height) + 4
|
|
// (conf target) = 142.
|
|
deprecatedLoopInChannelStart = 142
|
|
|
|
// expectedTotalLength is the expect total length of the
|
|
// serialized contract. It adds 8 (old loop in channel)
|
|
// + 1 (external htlc) = 9 bytes to
|
|
// deprecatedLoopInChannelStart.
|
|
expectedTotalLength = deprecatedLoopInChannelStart + 9
|
|
)
|
|
|
|
// Sanity check to see if the constants above match the contract
|
|
// bytes.
|
|
if len(contractBytes) != expectedTotalLength {
|
|
return errors.New("invalid serialized contract length")
|
|
}
|
|
|
|
// Copy the unchanged fields into the buffer.
|
|
b := &bytes.Buffer{}
|
|
_, err := b.Write(contractBytes[:deprecatedLoopInChannelStart])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// We now set the new last hop field to all zeroes to indicate
|
|
// that there is no restriction.
|
|
var noLastHop [33]byte
|
|
if _, err := b.Write(noLastHop[:]); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Append the remaining field ExternalHtlc.
|
|
_, err = b.Write(contractBytes[deprecatedLoopInChannelStart+8:])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return swapBucket.Put(contractKey, b.Bytes())
|
|
})
|
|
}
|