mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-10-11 05:25:03 +02:00
funding+channeldb: handle and persist channel fees
This commit is contained in:
@@ -276,6 +276,11 @@ var (
|
|||||||
// channelOpeningState for each channel that is currently in the process
|
// channelOpeningState for each channel that is currently in the process
|
||||||
// of being opened.
|
// of being opened.
|
||||||
channelOpeningStateBucket = []byte("channelOpeningState")
|
channelOpeningStateBucket = []byte("channelOpeningState")
|
||||||
|
|
||||||
|
// initialChannelFwdingPolicyBucket is the database bucket used to store
|
||||||
|
// the forwarding policy for each permanent channel that is currently
|
||||||
|
// in the process of being opened.
|
||||||
|
initialChannelFwdingPolicyBucket = []byte("initialChannelFwdingPolicy")
|
||||||
)
|
)
|
||||||
|
|
||||||
// DB is the primary datastore for the lnd daemon. The database stores
|
// DB is the primary datastore for the lnd daemon. The database stores
|
||||||
@@ -324,7 +329,9 @@ func Open(dbPath string, modifiers ...OptionModifier) (*DB, error) {
|
|||||||
|
|
||||||
// CreateWithBackend creates channeldb instance using the passed kvdb.Backend.
|
// CreateWithBackend creates channeldb instance using the passed kvdb.Backend.
|
||||||
// Any necessary schemas migrations due to updates will take place as necessary.
|
// Any necessary schemas migrations due to updates will take place as necessary.
|
||||||
func CreateWithBackend(backend kvdb.Backend, modifiers ...OptionModifier) (*DB, error) {
|
func CreateWithBackend(backend kvdb.Backend,
|
||||||
|
modifiers ...OptionModifier) (*DB, error) {
|
||||||
|
|
||||||
opts := DefaultOptions()
|
opts := DefaultOptions()
|
||||||
for _, modifier := range modifiers {
|
for _, modifier := range modifiers {
|
||||||
modifier(&opts)
|
modifier(&opts)
|
||||||
@@ -656,7 +663,9 @@ func (c *ChannelStateDB) FetchChannel(tx kvdb.RTx, chanPoint wire.OutPoint) (
|
|||||||
|
|
||||||
// The next layer down is all the chains that this node
|
// The next layer down is all the chains that this node
|
||||||
// has channels on with us.
|
// has channels on with us.
|
||||||
return nodeChanBucket.ForEach(func(chainHash, v []byte) error {
|
return nodeChanBucket.ForEach(func(chainHash,
|
||||||
|
v []byte) error {
|
||||||
|
|
||||||
// If there's a value, it's not a bucket so
|
// If there's a value, it's not a bucket so
|
||||||
// ignore it.
|
// ignore it.
|
||||||
if v != nil {
|
if v != nil {
|
||||||
@@ -1108,8 +1117,8 @@ func (c *ChannelStateDB) pruneLinkNode(openChannels []*OpenChannel,
|
|||||||
return c.linkNodeDB.DeleteLinkNode(remotePub)
|
return c.linkNodeDB.DeleteLinkNode(remotePub)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PruneLinkNodes attempts to prune all link nodes found within the database with
|
// PruneLinkNodes attempts to prune all link nodes found within the database
|
||||||
// whom we no longer have any open channels with.
|
// with whom we no longer have any open channels with.
|
||||||
func (c *ChannelStateDB) PruneLinkNodes() error {
|
func (c *ChannelStateDB) PruneLinkNodes() error {
|
||||||
allLinkNodes, err := c.linkNodeDB.FetchAllLinkNodes()
|
allLinkNodes, err := c.linkNodeDB.FetchAllLinkNodes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1290,6 +1299,64 @@ func (c *ChannelStateDB) AbandonChannel(chanPoint *wire.OutPoint,
|
|||||||
return dbChan.CloseChannel(summary, ChanStatusLocalCloseInitiator)
|
return dbChan.CloseChannel(summary, ChanStatusLocalCloseInitiator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SaveInitialFwdingPolicy saves the serialized forwarding policy for the
|
||||||
|
// provided permanent channel id to the initialChannelFwdingPolicyBucket.
|
||||||
|
func (c *ChannelStateDB) SaveInitialFwdingPolicy(chanID,
|
||||||
|
forwardingPolicy []byte) error {
|
||||||
|
|
||||||
|
return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
|
||||||
|
bucket, err := tx.CreateTopLevelBucket(
|
||||||
|
initialChannelFwdingPolicyBucket,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return bucket.Put(chanID, forwardingPolicy)
|
||||||
|
}, func() {})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInitialFwdingPolicy 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) GetInitialFwdingPolicy(chanID []byte) ([]byte, error) {
|
||||||
|
var serializedState []byte
|
||||||
|
err := kvdb.View(c.backend, func(tx kvdb.RTx) error {
|
||||||
|
bucket := tx.ReadBucket(initialChannelFwdingPolicyBucket)
|
||||||
|
if bucket == nil {
|
||||||
|
// If the bucket does not exist, it means we
|
||||||
|
// never added a channel fees to the db, so
|
||||||
|
// return ErrChannelNotFound.
|
||||||
|
return ErrChannelNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
stateBytes := bucket.Get(chanID)
|
||||||
|
if stateBytes == nil {
|
||||||
|
return ErrChannelNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
serializedState = append(serializedState, stateBytes...)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}, func() {
|
||||||
|
serializedState = nil
|
||||||
|
})
|
||||||
|
return serializedState, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteInitialFwdingPolicy removes the forwarding policy for a given channel
|
||||||
|
// from the database.
|
||||||
|
func (c *ChannelStateDB) DeleteInitialFwdingPolicy(chanID []byte) error {
|
||||||
|
return kvdb.Update(c.backend, func(tx kvdb.RwTx) error {
|
||||||
|
bucket := tx.ReadWriteBucket(initialChannelFwdingPolicyBucket)
|
||||||
|
if bucket == nil {
|
||||||
|
return ErrChannelNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return bucket.Delete(chanID)
|
||||||
|
}, func() {})
|
||||||
|
}
|
||||||
|
|
||||||
// SaveChannelOpeningState saves the serialized channel state for the provided
|
// SaveChannelOpeningState saves the serialized channel state for the provided
|
||||||
// chanPoint to the channelOpeningStateBucket.
|
// chanPoint to the channelOpeningStateBucket.
|
||||||
func (c *ChannelStateDB) SaveChannelOpeningState(outPoint,
|
func (c *ChannelStateDB) SaveChannelOpeningState(outPoint,
|
||||||
@@ -1308,7 +1375,9 @@ func (c *ChannelStateDB) SaveChannelOpeningState(outPoint,
|
|||||||
// GetChannelOpeningState fetches the serialized channel state for the provided
|
// GetChannelOpeningState fetches the serialized channel state for the provided
|
||||||
// outPoint from the database, or returns ErrChannelNotFound if the channel
|
// outPoint from the database, or returns ErrChannelNotFound if the channel
|
||||||
// is not found.
|
// is not found.
|
||||||
func (c *ChannelStateDB) GetChannelOpeningState(outPoint []byte) ([]byte, error) {
|
func (c *ChannelStateDB) GetChannelOpeningState(outPoint []byte) ([]byte,
|
||||||
|
error) {
|
||||||
|
|
||||||
var serializedState []byte
|
var serializedState []byte
|
||||||
err := kvdb.View(c.backend, func(tx kvdb.RTx) error {
|
err := kvdb.View(c.backend, func(tx kvdb.RTx) error {
|
||||||
bucket := tx.ReadBucket(channelOpeningStateBucket)
|
bucket := tx.ReadBucket(channelOpeningStateBucket)
|
||||||
@@ -1392,7 +1461,8 @@ func (d *DB) syncVersions(versions []mandatoryVersion) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Applying migration #%v", migrationVersions[i])
|
log.Infof("Applying migration #%v",
|
||||||
|
migrationVersions[i])
|
||||||
|
|
||||||
if err := migration(tx); err != nil {
|
if err := migration(tx); err != nil {
|
||||||
log.Infof("Unable to apply migration #%v",
|
log.Infof("Unable to apply migration #%v",
|
||||||
@@ -1532,7 +1602,9 @@ func fetchHistoricalChanBucket(tx kvdb.RTx,
|
|||||||
if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
|
if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
chanBucket := historicalChanBucket.NestedReadBucket(chanPointBuf.Bytes())
|
chanBucket := historicalChanBucket.NestedReadBucket(
|
||||||
|
chanPointBuf.Bytes(),
|
||||||
|
)
|
||||||
if chanBucket == nil {
|
if chanBucket == nil {
|
||||||
return nil, ErrChannelNotFound
|
return nil, ErrChannelNotFound
|
||||||
}
|
}
|
||||||
|
@@ -138,6 +138,9 @@ type reservationWithCtx struct {
|
|||||||
|
|
||||||
chanAmt btcutil.Amount
|
chanAmt btcutil.Amount
|
||||||
|
|
||||||
|
// forwardingPolicy is the policy provided by the initFundingMsg.
|
||||||
|
forwardingPolicy htlcswitch.ForwardingPolicy
|
||||||
|
|
||||||
// Constraints we require for the remote.
|
// Constraints we require for the remote.
|
||||||
remoteCsvDelay uint16
|
remoteCsvDelay uint16
|
||||||
remoteMinHtlc lnwire.MilliSatoshi
|
remoteMinHtlc lnwire.MilliSatoshi
|
||||||
@@ -197,6 +200,15 @@ type InitFundingMsg struct {
|
|||||||
// LocalFundingAmt is the size of the channel.
|
// LocalFundingAmt is the size of the channel.
|
||||||
LocalFundingAmt btcutil.Amount
|
LocalFundingAmt btcutil.Amount
|
||||||
|
|
||||||
|
// BaseFee is the base fee charged for routing payments regardless of the
|
||||||
|
// number of milli-satoshis sent.
|
||||||
|
BaseFee *uint64
|
||||||
|
|
||||||
|
// FeeRate is the fee rate in ppm (parts per million) that will be charged
|
||||||
|
// proportionally based on the value of each forwarded HTLC, the lowest
|
||||||
|
// possible rate is 0 with a granularity of 0.000001 (millionths).
|
||||||
|
FeeRate *uint64
|
||||||
|
|
||||||
// PushAmt is the amount pushed to the counterparty.
|
// PushAmt is the amount pushed to the counterparty.
|
||||||
PushAmt lnwire.MilliSatoshi
|
PushAmt lnwire.MilliSatoshi
|
||||||
|
|
||||||
@@ -1592,6 +1604,14 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer,
|
|||||||
minHtlc = acceptorResp.MinHtlcIn
|
minHtlc = acceptorResp.MinHtlcIn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we are handling a FundingOpen request then we need to
|
||||||
|
// specify the default channel fees since they are not provided
|
||||||
|
// by the responder interactively.
|
||||||
|
forwardingPolicy := htlcswitch.ForwardingPolicy{
|
||||||
|
BaseFee: f.cfg.DefaultRoutingPolicy.BaseFee,
|
||||||
|
FeeRate: f.cfg.DefaultRoutingPolicy.FeeRate,
|
||||||
|
}
|
||||||
|
|
||||||
// Once the reservation has been created successfully, we add it to
|
// Once the reservation has been created successfully, we add it to
|
||||||
// this peer's map of pending reservations to track this particular
|
// this peer's map of pending reservations to track this particular
|
||||||
// reservation until either abort or completion.
|
// reservation until either abort or completion.
|
||||||
@@ -1602,6 +1622,7 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer,
|
|||||||
resCtx := &reservationWithCtx{
|
resCtx := &reservationWithCtx{
|
||||||
reservation: reservation,
|
reservation: reservation,
|
||||||
chanAmt: amt,
|
chanAmt: amt,
|
||||||
|
forwardingPolicy: forwardingPolicy,
|
||||||
remoteCsvDelay: remoteCsvDelay,
|
remoteCsvDelay: remoteCsvDelay,
|
||||||
remoteMinHtlc: minHtlc,
|
remoteMinHtlc: minHtlc,
|
||||||
remoteMaxValue: remoteMaxValue,
|
remoteMaxValue: remoteMaxValue,
|
||||||
@@ -2110,6 +2131,9 @@ func (f *Manager) handleFundingCreated(peer lnpeer.Peer,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get forwarding policy before deleting the reservation context.
|
||||||
|
forwardingPolicy := resCtx.forwardingPolicy
|
||||||
|
|
||||||
// The channel is marked IsPending in the database, and can be removed
|
// The channel is marked IsPending in the database, and can be removed
|
||||||
// from the set of active reservations.
|
// from the set of active reservations.
|
||||||
f.deleteReservationCtx(peerKey, msg.PendingChannelID)
|
f.deleteReservationCtx(peerKey, msg.PendingChannelID)
|
||||||
@@ -2176,6 +2200,14 @@ func (f *Manager) handleFundingCreated(peer lnpeer.Peer,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// With a permanent channel id established we can save the respective
|
||||||
|
// forwarding policy in the database. In the channel announcement phase
|
||||||
|
// this forwarding policy is retrieved and applied.
|
||||||
|
err = f.saveInitialFwdingPolicy(channelID, &forwardingPolicy)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unable to store the forwarding policy: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Now that we've sent over our final signature for this channel, we'll
|
// Now that we've sent over our final signature for this channel, we'll
|
||||||
// send it to the ChainArbitrator so it can watch for any on-chain
|
// send it to the ChainArbitrator so it can watch for any on-chain
|
||||||
// actions during this final confirmation stage.
|
// actions during this final confirmation stage.
|
||||||
@@ -2257,6 +2289,14 @@ func (f *Manager) handleFundingSigned(peer lnpeer.Peer,
|
|||||||
f.localDiscoverySignals[permChanID] = make(chan struct{})
|
f.localDiscoverySignals[permChanID] = make(chan struct{})
|
||||||
f.localDiscoveryMtx.Unlock()
|
f.localDiscoveryMtx.Unlock()
|
||||||
|
|
||||||
|
// We have to store the forwardingPolicy before the reservation context
|
||||||
|
// is deleted. The policy will then be read and applied in
|
||||||
|
// newChanAnnouncement.
|
||||||
|
err = f.saveInitialFwdingPolicy(permChanID, &resCtx.forwardingPolicy)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unable to store the forwarding policy: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// The remote peer has responded with a signature for our commitment
|
// The remote peer has responded with a signature for our commitment
|
||||||
// transaction. We'll verify the signature for validity, then commit
|
// transaction. We'll verify the signature for validity, then commit
|
||||||
// the state to disk as we can now open the channel.
|
// the state to disk as we can now open the channel.
|
||||||
@@ -3082,6 +3122,15 @@ func (f *Manager) annAfterSixConfs(completeChan *channeldb.OpenChannel,
|
|||||||
return fmt.Errorf("unable to send node announcement "+
|
return fmt.Errorf("unable to send node announcement "+
|
||||||
"to peer %x: %v", pubKey, err)
|
"to peer %x: %v", pubKey, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For private channels we do not announce the channel policy
|
||||||
|
// to the network but still need to delete them from the
|
||||||
|
// database.
|
||||||
|
err = f.deleteInitialFwdingPolicy(chanID)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("Could not delete channel fees "+
|
||||||
|
"for chanId %x.", chanID)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, we'll wait until the funding transaction has
|
// Otherwise, we'll wait until the funding transaction has
|
||||||
// reached 6 confirmations before announcing it.
|
// reached 6 confirmations before announcing it.
|
||||||
@@ -3523,8 +3572,14 @@ func (f *Manager) newChanAnnouncement(localPubKey,
|
|||||||
if bytes.Compare(selfBytes, remoteBytes) == -1 {
|
if bytes.Compare(selfBytes, remoteBytes) == -1 {
|
||||||
copy(chanAnn.NodeID1[:], localPubKey.SerializeCompressed())
|
copy(chanAnn.NodeID1[:], localPubKey.SerializeCompressed())
|
||||||
copy(chanAnn.NodeID2[:], remotePubKey.SerializeCompressed())
|
copy(chanAnn.NodeID2[:], remotePubKey.SerializeCompressed())
|
||||||
copy(chanAnn.BitcoinKey1[:], localFundingKey.PubKey.SerializeCompressed())
|
copy(
|
||||||
copy(chanAnn.BitcoinKey2[:], remoteFundingKey.SerializeCompressed())
|
chanAnn.BitcoinKey1[:],
|
||||||
|
localFundingKey.PubKey.SerializeCompressed(),
|
||||||
|
)
|
||||||
|
copy(
|
||||||
|
chanAnn.BitcoinKey2[:],
|
||||||
|
remoteFundingKey.SerializeCompressed(),
|
||||||
|
)
|
||||||
|
|
||||||
// If we're the first node then update the chanFlags to
|
// If we're the first node then update the chanFlags to
|
||||||
// indicate the "direction" of the update.
|
// indicate the "direction" of the update.
|
||||||
@@ -3532,8 +3587,14 @@ func (f *Manager) newChanAnnouncement(localPubKey,
|
|||||||
} else {
|
} else {
|
||||||
copy(chanAnn.NodeID1[:], remotePubKey.SerializeCompressed())
|
copy(chanAnn.NodeID1[:], remotePubKey.SerializeCompressed())
|
||||||
copy(chanAnn.NodeID2[:], localPubKey.SerializeCompressed())
|
copy(chanAnn.NodeID2[:], localPubKey.SerializeCompressed())
|
||||||
copy(chanAnn.BitcoinKey1[:], remoteFundingKey.SerializeCompressed())
|
copy(
|
||||||
copy(chanAnn.BitcoinKey2[:], localFundingKey.PubKey.SerializeCompressed())
|
chanAnn.BitcoinKey1[:],
|
||||||
|
remoteFundingKey.SerializeCompressed(),
|
||||||
|
)
|
||||||
|
copy(
|
||||||
|
chanAnn.BitcoinKey2[:],
|
||||||
|
localFundingKey.PubKey.SerializeCompressed(),
|
||||||
|
)
|
||||||
|
|
||||||
// If we're the second node then update the chanFlags to
|
// If we're the second node then update the chanFlags to
|
||||||
// indicate the "direction" of the update.
|
// indicate the "direction" of the update.
|
||||||
@@ -3552,19 +3613,24 @@ func (f *Manager) newChanAnnouncement(localPubKey,
|
|||||||
Timestamp: uint32(time.Now().Unix()),
|
Timestamp: uint32(time.Now().Unix()),
|
||||||
MessageFlags: msgFlags,
|
MessageFlags: msgFlags,
|
||||||
ChannelFlags: chanFlags,
|
ChannelFlags: chanFlags,
|
||||||
TimeLockDelta: uint16(f.cfg.DefaultRoutingPolicy.TimeLockDelta),
|
TimeLockDelta: uint16(
|
||||||
|
f.cfg.DefaultRoutingPolicy.TimeLockDelta,
|
||||||
// We use the HtlcMinimumMsat that the remote party required us
|
),
|
||||||
// to use, as our ChannelUpdate will be used to carry HTLCs
|
|
||||||
// towards them.
|
|
||||||
HtlcMinimumMsat: fwdMinHTLC,
|
HtlcMinimumMsat: fwdMinHTLC,
|
||||||
HtlcMaximumMsat: fwdMaxHTLC,
|
HtlcMaximumMsat: fwdMaxHTLC,
|
||||||
|
|
||||||
BaseFee: uint32(f.cfg.DefaultRoutingPolicy.BaseFee),
|
|
||||||
FeeRate: uint32(f.cfg.DefaultRoutingPolicy.FeeRate),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ourPolicy != nil {
|
// The caller of newChanAnnouncement is expected to provide the initial
|
||||||
|
// forwarding policy to be announced. We abort the channel announcement
|
||||||
|
// if they are not provided.
|
||||||
|
storedFwdingPolicy, err := f.getInitialFwdingPolicy(chanID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("unable to generate channel "+
|
||||||
|
"update announcement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case ourPolicy != nil:
|
||||||
// If ourPolicy is non-nil, modify the default parameters of the
|
// If ourPolicy is non-nil, modify the default parameters of the
|
||||||
// ChannelUpdate.
|
// ChannelUpdate.
|
||||||
chanUpdateAnn.MessageFlags = ourPolicy.MessageFlags
|
chanUpdateAnn.MessageFlags = ourPolicy.MessageFlags
|
||||||
@@ -3576,6 +3642,21 @@ func (f *Manager) newChanAnnouncement(localPubKey,
|
|||||||
chanUpdateAnn.FeeRate = uint32(
|
chanUpdateAnn.FeeRate = uint32(
|
||||||
ourPolicy.FeeProportionalMillionths,
|
ourPolicy.FeeProportionalMillionths,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case storedFwdingPolicy != nil:
|
||||||
|
chanUpdateAnn.BaseFee = uint32(storedFwdingPolicy.BaseFee)
|
||||||
|
chanUpdateAnn.FeeRate = uint32(storedFwdingPolicy.FeeRate)
|
||||||
|
|
||||||
|
default:
|
||||||
|
log.Infof("No channel forwaring policy specified for channel "+
|
||||||
|
"announcement of ChannelID(%v). "+
|
||||||
|
"Assuming default fee parameters.", chanID)
|
||||||
|
chanUpdateAnn.BaseFee = uint32(
|
||||||
|
f.cfg.DefaultRoutingPolicy.BaseFee,
|
||||||
|
)
|
||||||
|
chanUpdateAnn.FeeRate = uint32(
|
||||||
|
f.cfg.DefaultRoutingPolicy.FeeRate,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the channel update announcement constructed, we'll generate a
|
// With the channel update announcement constructed, we'll generate a
|
||||||
@@ -3672,6 +3753,14 @@ func (f *Manager) announceChannel(localIDKey, remoteIDKey *btcec.PublicKey,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// After the fee parameters have been stored in the announcement
|
||||||
|
// we can delete them from the database.
|
||||||
|
err = f.deleteInitialFwdingPolicy(chanID)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("Could not delete channel fees for chanId %x.",
|
||||||
|
chanID)
|
||||||
|
}
|
||||||
|
|
||||||
// We only send the channel proof announcement and the node announcement
|
// We only send the channel proof announcement and the node announcement
|
||||||
// because addToRouterGraph previously sent the ChannelAnnouncement and
|
// because addToRouterGraph previously sent the ChannelAnnouncement and
|
||||||
// the ChannelUpdate announcement messages. The channel proof and node
|
// the ChannelUpdate announcement messages. The channel proof and node
|
||||||
@@ -3792,6 +3881,8 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
|
|||||||
var (
|
var (
|
||||||
peerKey = msg.Peer.IdentityKey()
|
peerKey = msg.Peer.IdentityKey()
|
||||||
localAmt = msg.LocalFundingAmt
|
localAmt = msg.LocalFundingAmt
|
||||||
|
baseFee = msg.BaseFee
|
||||||
|
feeRate = msg.FeeRate
|
||||||
minHtlcIn = msg.MinHtlcIn
|
minHtlcIn = msg.MinHtlcIn
|
||||||
remoteCsvDelay = msg.RemoteCsvDelay
|
remoteCsvDelay = msg.RemoteCsvDelay
|
||||||
maxValue = msg.MaxValueInFlight
|
maxValue = msg.MaxValueInFlight
|
||||||
@@ -3985,6 +4076,22 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
|
|||||||
maxHtlcs = f.cfg.RequiredRemoteMaxHTLCs(capacity)
|
maxHtlcs = f.cfg.RequiredRemoteMaxHTLCs(capacity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare the optional channel fee values from the initFundingMsg.
|
||||||
|
// If useBaseFee or useFeeRate are false the client did not
|
||||||
|
// provide fee values hence we assume default fee settings from
|
||||||
|
// the config.
|
||||||
|
forwardingPolicy := htlcswitch.ForwardingPolicy{
|
||||||
|
BaseFee: f.cfg.DefaultRoutingPolicy.BaseFee,
|
||||||
|
FeeRate: f.cfg.DefaultRoutingPolicy.FeeRate,
|
||||||
|
}
|
||||||
|
if baseFee != nil {
|
||||||
|
forwardingPolicy.BaseFee = lnwire.MilliSatoshi(*baseFee)
|
||||||
|
}
|
||||||
|
|
||||||
|
if feeRate != nil {
|
||||||
|
forwardingPolicy.FeeRate = lnwire.MilliSatoshi(*feeRate)
|
||||||
|
}
|
||||||
|
|
||||||
// If a pending channel map for this peer isn't already created, then
|
// If a pending channel map for this peer isn't already created, then
|
||||||
// we create one, ultimately allowing us to track this pending
|
// we create one, ultimately allowing us to track this pending
|
||||||
// reservation within the target peer.
|
// reservation within the target peer.
|
||||||
@@ -3996,6 +4103,7 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
|
|||||||
|
|
||||||
resCtx := &reservationWithCtx{
|
resCtx := &reservationWithCtx{
|
||||||
chanAmt: capacity,
|
chanAmt: capacity,
|
||||||
|
forwardingPolicy: forwardingPolicy,
|
||||||
remoteCsvDelay: remoteCsvDelay,
|
remoteCsvDelay: remoteCsvDelay,
|
||||||
remoteMinHtlc: minHtlcIn,
|
remoteMinHtlc: minHtlcIn,
|
||||||
remoteMaxValue: maxValue,
|
remoteMaxValue: maxValue,
|
||||||
@@ -4267,6 +4375,70 @@ func copyPubKey(pub *btcec.PublicKey) *btcec.PublicKey {
|
|||||||
return btcec.NewPublicKey(&tmp.X, &tmp.Y)
|
return btcec.NewPublicKey(&tmp.X, &tmp.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// saveInitialFwdingPolicy saves the forwarding policy for the provided
|
||||||
|
// chanPoint in the channelOpeningStateBucket.
|
||||||
|
func (f *Manager) saveInitialFwdingPolicy(permChanID 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.Wallet.Cfg.Database.SaveInitialFwdingPolicy(
|
||||||
|
chanID, scratch,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getInitialFwdingPolicy 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) getInitialFwdingPolicy(permChanID lnwire.ChannelID) (
|
||||||
|
*htlcswitch.ForwardingPolicy, error) {
|
||||||
|
|
||||||
|
chanID := make([]byte, 32)
|
||||||
|
copy(chanID, permChanID[:])
|
||||||
|
|
||||||
|
value, err := f.cfg.Wallet.Cfg.Database.GetInitialFwdingPolicy(
|
||||||
|
chanID,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var fwdingPolicy htlcswitch.ForwardingPolicy
|
||||||
|
fwdingPolicy.MinHTLCOut = lnwire.MilliSatoshi(
|
||||||
|
byteOrder.Uint64(value[:8]),
|
||||||
|
)
|
||||||
|
fwdingPolicy.MaxHTLC = lnwire.MilliSatoshi(
|
||||||
|
byteOrder.Uint64(value[8:16]),
|
||||||
|
)
|
||||||
|
fwdingPolicy.BaseFee = lnwire.MilliSatoshi(
|
||||||
|
byteOrder.Uint64(value[16:24]),
|
||||||
|
)
|
||||||
|
fwdingPolicy.FeeRate = lnwire.MilliSatoshi(
|
||||||
|
byteOrder.Uint64(value[24:32]),
|
||||||
|
)
|
||||||
|
fwdingPolicy.TimeLockDelta = byteOrder.Uint32(value[32:36])
|
||||||
|
|
||||||
|
return &fwdingPolicy, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteInitialFwdingPolicy removes channel fees for this chanID from
|
||||||
|
// the database.
|
||||||
|
func (f *Manager) deleteInitialFwdingPolicy(permChanID lnwire.ChannelID) error {
|
||||||
|
chanID := make([]byte, 32)
|
||||||
|
copy(chanID, permChanID[:])
|
||||||
|
|
||||||
|
return f.cfg.Wallet.Cfg.Database.DeleteInitialFwdingPolicy(chanID)
|
||||||
|
}
|
||||||
|
|
||||||
// saveChannelOpeningState saves the channelOpeningState for the provided
|
// saveChannelOpeningState saves the channelOpeningState for the provided
|
||||||
// chanPoint to the channelOpeningStateBucket.
|
// chanPoint to the channelOpeningStateBucket.
|
||||||
func (f *Manager) saveChannelOpeningState(chanPoint *wire.OutPoint,
|
func (f *Manager) saveChannelOpeningState(chanPoint *wire.OutPoint,
|
||||||
|
Reference in New Issue
Block a user