2
0
mirror of https://github.com/lightninglabs/loop synced 2024-11-08 01:10:29 +00:00
loop/loopdb/migration_03_last_hop.go
Joost Jager 535e964ec9
loopdb: migrate loop in channel to last hop
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.
2020-02-17 19:59:05 +01:00

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())
})
}