loopdb/loopout: add field SwapPublicationDeadline to LoopOutContract

We also add a migration for the new LoopOut DB format.
pull/75/head
Johan T. Halseth 5 years ago
parent a6bb2e51c5
commit 034cba5b95
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26

@ -45,6 +45,12 @@ type LoopOutContract struct {
// MaxPrepayRoutingFee is the maximum off-chain fee in msat that may be
// paid for the prepayment to the server.
MaxPrepayRoutingFee btcutil.Amount
// SwapPublicationDeadline is a timestamp that the server commits to
// have the on-chain swap published by. It is set by the client to
// allow the server to delay the publication in exchange for possibly
// lower fees.
SwapPublicationDeadline time.Time
}
// LoopOut is a combination of the contract and the updates.
@ -158,6 +164,13 @@ func deserializeLoopOutContract(value []byte, chainParams *chaincfg.Params) (
contract.UnchargeChannel = &unchargeChannel
}
var deadlineNano int64
err = binary.Read(r, byteOrder, &deadlineNano)
if err != nil {
return nil, err
}
contract.SwapPublicationDeadline = time.Unix(0, deadlineNano)
return &contract, nil
}
@ -243,5 +256,10 @@ func serializeLoopOutContract(swap *LoopOutContract) (
return nil, err
}
err = binary.Write(&b, byteOrder, swap.SwapPublicationDeadline.UnixNano())
if err != nil {
return nil, err
}
return b.Bytes(), nil
}

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"github.com/btcsuite/btcd/chaincfg"
"github.com/coreos/bbolt"
)
@ -24,14 +25,17 @@ var (
// migration is a function which takes a prior outdated version of the database
// instances and mutates the key/bucket structure to arrive at a more
// up-to-date version of the database.
type migration func(tx *bbolt.Tx) error
type migration func(tx *bbolt.Tx, chainParams *chaincfg.Params) error
var (
// dbVersions is storing all versions of database. If current version
// of database don't match with latest version this list will be used
// for retrieving all migration function that are need to apply to the
// current db.
migrations = []migration{migrateCosts}
migrations = []migration{
migrateCosts,
migrateSwapPublicationDeadline,
}
latestDBVersion = uint32(len(migrations))
)
@ -76,7 +80,7 @@ func setDBVersion(tx *bbolt.Tx, version uint32) error {
// syncVersions function is used for safe db version synchronization. It
// applies migration functions to the current database and recovers the
// previous state of db if at least one error/panic appeared during migration.
func syncVersions(db *bbolt.DB) error {
func syncVersions(db *bbolt.DB, chainParams *chaincfg.Params) error {
currentVersion, err := getDBVersion(db)
if err != nil {
return err
@ -112,7 +116,7 @@ func syncVersions(db *bbolt.DB) error {
log.Infof("Applying migration #%v", v+1)
migration := migrations[v]
if err := migration(tx); err != nil {
if err := migration(tx, chainParams); err != nil {
log.Infof("Unable to apply migration #%v",
v+1)
return err

@ -4,12 +4,13 @@ import (
"errors"
"fmt"
"github.com/btcsuite/btcd/chaincfg"
"github.com/coreos/bbolt"
)
// noMigrationAvailable is the fall back migration in case there is no migration
// implemented.
func migrateCosts(tx *bbolt.Tx) error {
func migrateCosts(tx *bbolt.Tx, _ *chaincfg.Params) error {
if err := migrateCostsForBucket(tx, loopInBucketKey); err != nil {
return err
}

@ -0,0 +1,58 @@
package loopdb
import (
"bytes"
"errors"
"fmt"
"github.com/btcsuite/btcd/chaincfg"
"github.com/coreos/bbolt"
)
// migrateSwapPublicationDeadline migrates the database to v02, by adding the
// SwapPublicationDeadline field to loop out contracts.
func migrateSwapPublicationDeadline(tx *bbolt.Tx, chainParams *chaincfg.Params) error {
rootBucket := tx.Bucket(loopOutBucketKey)
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")
}
// Write the current contract serialization into a buffer.
b := &bytes.Buffer{}
if _, err := b.Write(contractBytes); err != nil {
return err
}
// We migrate to the new format by copying the first 8 bytes
// (the creation time) to the end (the swap deadline)
var swapDeadline [8]byte
copy(swapDeadline[:], contractBytes[:8])
if _, err := b.Write(swapDeadline[:]); err != nil {
return err
}
return swapBucket.Put(contractKey, b.Bytes())
})
}

@ -135,7 +135,7 @@ func NewBoltSwapStore(dbPath string, chainParams *chaincfg.Params) (
// Finally, before we start, we'll sync the DB versions to pick up any
// possible DB migrations.
err = syncVersions(bdb)
err = syncVersions(bdb, chainParams)
if err != nil {
return nil, err
}

@ -82,12 +82,13 @@ func TestLoopOutStore(t *testing.T) {
// doesn't interfere with DeepEqual.
InitiationTime: time.Unix(0, initiationTime.UnixNano()),
},
MaxPrepayRoutingFee: 40,
PrepayInvoice: "prepayinvoice",
DestAddr: destAddr,
SwapInvoice: "swapinvoice",
MaxSwapRoutingFee: 30,
SweepConfTarget: 2,
MaxPrepayRoutingFee: 40,
PrepayInvoice: "prepayinvoice",
DestAddr: destAddr,
SwapInvoice: "swapinvoice",
MaxSwapRoutingFee: 30,
SweepConfTarget: 2,
SwapPublicationDeadline: time.Unix(0, initiationTime.UnixNano()),
}
// checkSwap is a test helper function that'll assert the state of a

Loading…
Cancel
Save