From 59b5fb156599233edeef96f3b64c9a8d75fc4880 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 17 Jul 2023 12:53:23 +0200 Subject: [PATCH] channeldb+funding: move policy encoding into channel DB --- channeldb/forwarding_policy.go | 63 +++++++++++++++++++++++++++------- channeldb/models/channel.go | 38 ++++++++++++++++++++ funding/manager.go | 62 +++++++++++++-------------------- 3 files changed, 111 insertions(+), 52 deletions(-) diff --git a/channeldb/forwarding_policy.go b/channeldb/forwarding_policy.go index 8d86b8624..2a4123045 100644 --- a/channeldb/forwarding_policy.go +++ b/channeldb/forwarding_policy.go @@ -1,6 +1,10 @@ package channeldb -import "github.com/lightningnetwork/lnd/kvdb" +import ( + "github.com/lightningnetwork/lnd/channeldb/models" + "github.com/lightningnetwork/lnd/kvdb" + "github.com/lightningnetwork/lnd/lnwire" +) var ( // initialChannelForwardingPolicyBucket is the database bucket used to @@ -13,8 +17,18 @@ var ( // SaveInitialForwardingPolicy saves the serialized forwarding policy for the // provided permanent channel id to the initialChannelForwardingPolicyBucket. -func (c *ChannelStateDB) SaveInitialForwardingPolicy(chanID, - forwardingPolicy []byte) error { +func (c *ChannelStateDB) SaveInitialForwardingPolicy(chanID lnwire.ChannelID, + forwardingPolicy *models.ForwardingPolicy) error { + + chanIDCopy := make([]byte, 32) + copy(chanIDCopy, chanID[:]) + + scratch := make([]byte, 36) + byteOrder.PutUint64(scratch[:8], uint64(forwardingPolicy.MinHTLCOut)) + byteOrder.PutUint64(scratch[8:16], uint64(forwardingPolicy.MaxHTLC)) + byteOrder.PutUint64(scratch[16:24], uint64(forwardingPolicy.BaseFee)) + byteOrder.PutUint64(scratch[24:32], uint64(forwardingPolicy.FeeRate)) + byteOrder.PutUint32(scratch[32:], forwardingPolicy.TimeLockDelta) return kvdb.Update(c.backend, func(tx kvdb.RwTx) error { bucket, err := tx.CreateTopLevelBucket( @@ -24,17 +38,20 @@ func (c *ChannelStateDB) SaveInitialForwardingPolicy(chanID, return err } - return bucket.Put(chanID, forwardingPolicy) + return bucket.Put(chanIDCopy, scratch) }, func() {}) } // GetInitialForwardingPolicy fetches the serialized forwarding policy for the // provided channel id from the database, or returns ErrChannelNotFound if // a forwarding policy for this channel id is not found. -func (c *ChannelStateDB) GetInitialForwardingPolicy(chanID []byte) ([]byte, - error) { +func (c *ChannelStateDB) GetInitialForwardingPolicy( + chanID lnwire.ChannelID) (*models.ForwardingPolicy, error) { - var serializedState []byte + chanIDCopy := make([]byte, 32) + copy(chanIDCopy, chanID[:]) + + var forwardingPolicy *models.ForwardingPolicy err := kvdb.View(c.backend, func(tx kvdb.RTx) error { bucket := tx.ReadBucket(initialChannelForwardingPolicyBucket) if bucket == nil { @@ -44,23 +61,43 @@ func (c *ChannelStateDB) GetInitialForwardingPolicy(chanID []byte) ([]byte, return ErrChannelNotFound } - stateBytes := bucket.Get(chanID) + stateBytes := bucket.Get(chanIDCopy) if stateBytes == nil { return ErrChannelNotFound } - serializedState = append(serializedState, stateBytes...) + forwardingPolicy = &models.ForwardingPolicy{ + MinHTLCOut: lnwire.MilliSatoshi( + byteOrder.Uint64(stateBytes[:8]), + ), + MaxHTLC: lnwire.MilliSatoshi( + byteOrder.Uint64(stateBytes[8:16]), + ), + BaseFee: lnwire.MilliSatoshi( + byteOrder.Uint64(stateBytes[16:24]), + ), + FeeRate: lnwire.MilliSatoshi( + byteOrder.Uint64(stateBytes[24:32]), + ), + TimeLockDelta: byteOrder.Uint32(stateBytes[32:36]), + } return nil }, func() { - serializedState = nil + forwardingPolicy = nil }) - return serializedState, err + + return forwardingPolicy, err } // DeleteInitialForwardingPolicy removes the forwarding policy for a given // channel from the database. -func (c *ChannelStateDB) DeleteInitialForwardingPolicy(chanID []byte) error { +func (c *ChannelStateDB) DeleteInitialForwardingPolicy( + chanID lnwire.ChannelID) error { + + chanIDCopy := make([]byte, 32) + copy(chanIDCopy, chanID[:]) + return kvdb.Update(c.backend, func(tx kvdb.RwTx) error { bucket := tx.ReadWriteBucket( initialChannelForwardingPolicyBucket, @@ -69,6 +106,6 @@ func (c *ChannelStateDB) DeleteInitialForwardingPolicy(chanID []byte) error { return ErrChannelNotFound } - return bucket.Delete(chanID) + return bucket.Delete(chanIDCopy) }, func() {}) } diff --git a/channeldb/models/channel.go b/channeldb/models/channel.go index d05165309..4a65462e7 100644 --- a/channeldb/models/channel.go +++ b/channeldb/models/channel.go @@ -90,3 +90,41 @@ func (k *CircuitKey) Decode(r io.Reader) error { func (k CircuitKey) String() string { return fmt.Sprintf("(Chan ID=%s, HTLC ID=%d)", k.ChanID, k.HtlcID) } + +// ForwardingPolicy describes the set of constraints that a given ChannelLink +// is to adhere to when forwarding HTLC's. For each incoming HTLC, this set of +// constraints will be consulted in order to ensure that adequate fees are +// paid, and our time-lock parameters are respected. In the event that an +// incoming HTLC violates any of these constraints, it is to be _rejected_ with +// the error possibly carrying along a ChannelUpdate message that includes the +// latest policy. +type ForwardingPolicy struct { + // MinHTLCOut is the smallest HTLC that is to be forwarded. + MinHTLCOut lnwire.MilliSatoshi + + // MaxHTLC is the largest HTLC that is to be forwarded. + MaxHTLC lnwire.MilliSatoshi + + // BaseFee is the base fee, expressed in milli-satoshi that must be + // paid for each incoming HTLC. This field, combined with FeeRate is + // used to compute the required fee for a given HTLC. + BaseFee lnwire.MilliSatoshi + + // FeeRate is the fee rate, expressed in milli-satoshi that must be + // paid for each incoming HTLC. This field combined with BaseFee is + // used to compute the required fee for a given HTLC. + FeeRate lnwire.MilliSatoshi + + // TimeLockDelta is the absolute time-lock value, expressed in blocks, + // that will be subtracted from an incoming HTLC's timelock value to + // create the time-lock value for the forwarded outgoing HTLC. The + // following constraint MUST hold for an HTLC to be forwarded: + // + // * incomingHtlc.timeLock - timeLockDelta = fwdInfo.OutgoingCTLV + // + // where fwdInfo is the forwarding information extracted from the + // per-hop payload of the incoming HTLC's onion packet. + TimeLockDelta uint32 + + // TODO(roasbeef): add fee module inside of switch +} diff --git a/funding/manager.go b/funding/manager.go index 5469fe1f8..e9eb3ad48 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -20,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/chainreg" "github.com/lightningnetwork/lnd/chanacceptor" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/discovery" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" @@ -4636,62 +4637,45 @@ func (f *Manager) defaultForwardingPolicy( // saveInitialForwardingPolicy saves the forwarding policy for the provided // chanPoint in the channelOpeningStateBucket. -func (f *Manager) saveInitialForwardingPolicy(permChanID lnwire.ChannelID, +func (f *Manager) saveInitialForwardingPolicy(chanID lnwire.ChannelID, forwardingPolicy *htlcswitch.ForwardingPolicy) error { - chanID := make([]byte, 32) - copy(chanID, permChanID[:]) - - scratch := make([]byte, 36) - byteOrder.PutUint64(scratch[:8], uint64(forwardingPolicy.MinHTLCOut)) - byteOrder.PutUint64(scratch[8:16], uint64(forwardingPolicy.MaxHTLC)) - byteOrder.PutUint64(scratch[16:24], uint64(forwardingPolicy.BaseFee)) - byteOrder.PutUint64(scratch[24:32], uint64(forwardingPolicy.FeeRate)) - byteOrder.PutUint32(scratch[32:], forwardingPolicy.TimeLockDelta) - - return f.cfg.ChannelDB.SaveInitialForwardingPolicy(chanID, scratch) + return f.cfg.ChannelDB.SaveInitialForwardingPolicy( + chanID, &models.ForwardingPolicy{ + MinHTLCOut: forwardingPolicy.MinHTLCOut, + MaxHTLC: forwardingPolicy.MaxHTLC, + BaseFee: forwardingPolicy.BaseFee, + FeeRate: forwardingPolicy.FeeRate, + TimeLockDelta: forwardingPolicy.TimeLockDelta, + }, + ) } // getInitialForwardingPolicy fetches the initial forwarding policy for a given // channel id from the database which will be applied during the channel // announcement phase. func (f *Manager) getInitialForwardingPolicy( - permChanID lnwire.ChannelID) (*htlcswitch.ForwardingPolicy, error) { + chanID lnwire.ChannelID) (*htlcswitch.ForwardingPolicy, error) { - chanID := make([]byte, 32) - copy(chanID, permChanID[:]) - - value, err := f.cfg.ChannelDB.GetInitialForwardingPolicy(chanID) + dbPolicy, err := f.cfg.ChannelDB.GetInitialForwardingPolicy( + chanID, + ) if err != nil { return nil, err } - var forwardingPolicy htlcswitch.ForwardingPolicy - forwardingPolicy.MinHTLCOut = lnwire.MilliSatoshi( - byteOrder.Uint64(value[:8]), - ) - forwardingPolicy.MaxHTLC = lnwire.MilliSatoshi( - byteOrder.Uint64(value[8:16]), - ) - forwardingPolicy.BaseFee = lnwire.MilliSatoshi( - byteOrder.Uint64(value[16:24]), - ) - forwardingPolicy.FeeRate = lnwire.MilliSatoshi( - byteOrder.Uint64(value[24:32]), - ) - forwardingPolicy.TimeLockDelta = byteOrder.Uint32(value[32:36]) - - return &forwardingPolicy, nil + return &htlcswitch.ForwardingPolicy{ + MinHTLCOut: dbPolicy.MinHTLCOut, + MaxHTLC: dbPolicy.MaxHTLC, + BaseFee: dbPolicy.BaseFee, + FeeRate: dbPolicy.FeeRate, + TimeLockDelta: dbPolicy.TimeLockDelta, + }, nil } // deleteInitialForwardingPolicy removes channel fees for this chanID from // the database. -func (f *Manager) deleteInitialForwardingPolicy( - permChanID lnwire.ChannelID) error { - - chanID := make([]byte, 32) - copy(chanID, permChanID[:]) - +func (f *Manager) deleteInitialForwardingPolicy(chanID lnwire.ChannelID) error { return f.cfg.ChannelDB.DeleteInitialForwardingPolicy(chanID) }