2
0
mirror of https://github.com/lightninglabs/loop synced 2024-11-08 01:10:29 +00:00
loop/loopdb/loopin.go
Andras Banki-Horvath da4bcbea10
loopdb: refactor the SwapContract to hold all HTLC keys
This commit adds a new struct to hold all HTLC keys and refactors the
SwapContract which is used by both loopin and loopout swaps to use this
new struct. The newly added internal keys will for now hold the script
keys to keep everything equivalent but are already stored and read back
if the protocol version is set to MuSig2.
2023-03-20 20:08:43 +01:00

214 lines
4.9 KiB
Go

package loopdb
import (
"bytes"
"encoding/binary"
"fmt"
"time"
"github.com/coreos/bbolt"
"github.com/lightninglabs/loop/labels"
"github.com/lightningnetwork/lnd/routing/route"
)
// LoopInContract contains the data that is serialized to persistent storage for
// pending loop in swaps.
type LoopInContract struct {
SwapContract
// SweepConfTarget specifies the targeted confirmation target for the
// client sweep tx.
HtlcConfTarget int32
// LastHop is the last hop to use for the loop in swap (optional).
LastHop *route.Vertex
// ExternalHtlc specifies whether the htlc is published by an external
// source.
ExternalHtlc bool
}
// LoopIn is a combination of the contract and the updates.
type LoopIn struct {
Loop
Contract *LoopInContract
}
// LastUpdateTime returns the last update time of this swap.
func (s *LoopIn) LastUpdateTime() time.Time {
lastUpdate := s.LastUpdate()
if lastUpdate == nil {
return s.Contract.InitiationTime
}
return lastUpdate.Time
}
// serializeLoopInContract serialize the loop in contract into a byte slice.
func serializeLoopInContract(swap *LoopInContract) (
[]byte, error) {
var b bytes.Buffer
if err := binary.Write(&b, byteOrder, swap.InitiationTime.UnixNano()); err != nil {
return nil, err
}
if err := binary.Write(&b, byteOrder, swap.Preimage); err != nil {
return nil, err
}
if err := binary.Write(&b, byteOrder, swap.AmountRequested); err != nil {
return nil, err
}
n, err := b.Write(swap.HtlcKeys.SenderScriptKey[:])
if err != nil {
return nil, err
}
if n != keyLength {
return nil, fmt.Errorf("sender key has invalid length")
}
n, err = b.Write(swap.HtlcKeys.ReceiverScriptKey[:])
if err != nil {
return nil, err
}
if n != keyLength {
return nil, fmt.Errorf("receiver key has invalid length")
}
if err := binary.Write(&b, byteOrder, swap.CltvExpiry); err != nil {
return nil, err
}
if err := binary.Write(&b, byteOrder, swap.MaxMinerFee); err != nil {
return nil, err
}
if err := binary.Write(&b, byteOrder, swap.MaxSwapFee); err != nil {
return nil, err
}
if err := binary.Write(&b, byteOrder, swap.InitiationHeight); err != nil {
return nil, err
}
if err := binary.Write(&b, byteOrder, swap.HtlcConfTarget); err != nil {
return nil, err
}
var lastHop route.Vertex
if swap.LastHop != nil {
lastHop = *swap.LastHop
}
if err := binary.Write(&b, byteOrder, lastHop[:]); err != nil {
return nil, err
}
if err := binary.Write(&b, byteOrder, swap.ExternalHtlc); err != nil {
return nil, err
}
return b.Bytes(), nil
}
// putLabel performs validation of a label and writes it to the bucket provided
// under the label key if it is non-zero.
func putLabel(bucket *bbolt.Bucket, label string) error {
if len(label) == 0 {
return nil
}
// Check that the label does not exceed our maximum length.
if len(label) > labels.MaxLength {
return labels.ErrLabelTooLong
}
return bucket.Put(labelKey, []byte(label))
}
// getLabel attempts to get an optional label stored under the label key in a
// bucket. If it is not present, an empty label is returned.
func getLabel(bucket *bbolt.Bucket) string {
label := bucket.Get(labelKey)
if label == nil {
return ""
}
return string(label)
}
// deserializeLoopInContract deserializes the loop in contract from a byte slice.
func deserializeLoopInContract(value []byte) (*LoopInContract, error) {
r := bytes.NewReader(value)
contract := LoopInContract{}
var err error
var unixNano int64
if err := binary.Read(r, byteOrder, &unixNano); err != nil {
return nil, err
}
contract.InitiationTime = time.Unix(0, unixNano)
if err := binary.Read(r, byteOrder, &contract.Preimage); err != nil {
return nil, err
}
err = binary.Read(r, byteOrder, &contract.AmountRequested)
if err != nil {
return nil, err
}
n, err := r.Read(contract.HtlcKeys.SenderScriptKey[:])
if err != nil {
return nil, err
}
if n != keyLength {
return nil, fmt.Errorf("sender key has invalid length")
}
n, err = r.Read(contract.HtlcKeys.ReceiverScriptKey[:])
if err != nil {
return nil, err
}
if n != keyLength {
return nil, fmt.Errorf("receiver key has invalid length")
}
if err := binary.Read(r, byteOrder, &contract.CltvExpiry); err != nil {
return nil, err
}
if err := binary.Read(r, byteOrder, &contract.MaxMinerFee); err != nil {
return nil, err
}
if err := binary.Read(r, byteOrder, &contract.MaxSwapFee); err != nil {
return nil, err
}
if err := binary.Read(r, byteOrder, &contract.InitiationHeight); err != nil {
return nil, err
}
if err := binary.Read(r, byteOrder, &contract.HtlcConfTarget); err != nil {
return nil, err
}
var lastHop route.Vertex
if err := binary.Read(r, byteOrder, lastHop[:]); err != nil {
return nil, err
}
var noLastHop route.Vertex
if lastHop != noLastHop {
contract.LastHop = &lastHop
}
if err := binary.Read(r, byteOrder, &contract.ExternalHtlc); err != nil {
return nil, err
}
return &contract, nil
}