discovery+switch: apply zero forwarding policy updates in-memory as well as on disk
In this commit, we fix a bug where if a user updates a forwarding policy to be zero, the update will be applied to the policy correctly on-disk, but not in-memory. We solve this issue by having the gossiper return the list of on-disk updated policies and passing these policies to the switch, so the switch can assume that zero-valued fields are intentional and not just uninitialized.
This commit is contained in:
1 parent
2cf10ada0f
commit
8ce7f82da0
6 files changed
+109
-100
No files matched your search
+4
-19
@@ -2156,31 +2156,16 @@ func (l *channelLink) AttachMailBox(mailbox MailBox) {
|
||||
|
||||
// UpdateForwardingPolicy updates the forwarding policy for the target
|
||||
// ChannelLink. Once updated, the link will use the new forwarding policy to
|
||||
// govern if it an incoming HTLC should be forwarded or not. Note that this
|
||||
// processing of the new policy will ensure that uninitialized fields in the
|
||||
// passed policy won't override already initialized fields in the current
|
||||
// policy.
|
||||
// govern if it an incoming HTLC should be forwarded or not. We assume that
|
||||
// fields that are zero are intentionally set to zero, so we'll use newPolicy to
|
||||
// update all of the link's FwrdingPolicy's values.
|
||||
//
|
||||
// NOTE: Part of the ChannelLink interface.
|
||||
func (l *channelLink) UpdateForwardingPolicy(newPolicy ForwardingPolicy) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
// In order to avoid overriding a valid policy with a "null" field in
|
||||
// the new policy, we'll only update to the set sub policy if the new
|
||||
// value isn't uninitialized.
|
||||
if newPolicy.BaseFee != 0 {
|
||||
l.cfg.FwrdingPolicy.BaseFee = newPolicy.BaseFee
|
||||
}
|
||||
if newPolicy.FeeRate != 0 {
|
||||
l.cfg.FwrdingPolicy.FeeRate = newPolicy.FeeRate
|
||||
}
|
||||
if newPolicy.TimeLockDelta != 0 {
|
||||
l.cfg.FwrdingPolicy.TimeLockDelta = newPolicy.TimeLockDelta
|
||||
}
|
||||
if newPolicy.MinHTLC != 0 {
|
||||
l.cfg.FwrdingPolicy.MinHTLC = newPolicy.MinHTLC
|
||||
}
|
||||
l.cfg.FwrdingPolicy = newPolicy
|
||||
}
|
||||
|
||||
// HtlcSatifiesPolicy should return a nil error if the passed HTLC details
|
||||
|
||||
@@ -5530,9 +5530,9 @@ func TestForwardingAsymmetricTimeLockPolicies(t *testing.T) {
|
||||
// Now that each of the links are up, we'll modify the link from Alice
|
||||
// -> Bob to have a greater time lock delta than that of the link of
|
||||
// Bob -> Carol.
|
||||
n.firstBobChannelLink.UpdateForwardingPolicy(ForwardingPolicy{
|
||||
TimeLockDelta: 7,
|
||||
})
|
||||
newPolicy := n.firstBobChannelLink.cfg.FwrdingPolicy
|
||||
newPolicy.TimeLockDelta = 7
|
||||
n.firstBobChannelLink.UpdateForwardingPolicy(newPolicy)
|
||||
|
||||
// Now that the Alice -> Bob link has been updated, we'll craft and
|
||||
// send a payment from Alice -> Carol. This should succeed as normal,
|
||||
|
||||
+31
-40
@@ -439,60 +439,51 @@ func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, paymentID uint64,
|
||||
}
|
||||
|
||||
// UpdateForwardingPolicies sends a message to the switch to update the
|
||||
// forwarding policies for the set of target channels. If the set of targeted
|
||||
// channels is nil, then the forwarding policies for all active channels with
|
||||
// be updated.
|
||||
// forwarding policies for the set of target channels, keyed in chanPolicies.
|
||||
//
|
||||
// NOTE: This function is synchronous and will block until either the
|
||||
// forwarding policies for all links have been updated, or the switch shuts
|
||||
// down.
|
||||
func (s *Switch) UpdateForwardingPolicies(newPolicy ForwardingPolicy,
|
||||
targetChans ...wire.OutPoint) error {
|
||||
func (s *Switch) UpdateForwardingPolicies(
|
||||
chanPolicies map[wire.OutPoint]*channeldb.ChannelEdgePolicy) {
|
||||
|
||||
log.Debugf("Updating link policies: %v", newLogClosure(func() string {
|
||||
return spew.Sdump(newPolicy)
|
||||
log.Tracef("Updating link policies: %v", newLogClosure(func() string {
|
||||
return spew.Sdump(chanPolicies)
|
||||
}))
|
||||
|
||||
var linksToUpdate []ChannelLink
|
||||
|
||||
s.indexMtx.RLock()
|
||||
|
||||
// If no channels have been targeted, then we'll collect all inks to
|
||||
// update their policies.
|
||||
if len(targetChans) == 0 {
|
||||
for _, link := range s.linkIndex {
|
||||
linksToUpdate = append(linksToUpdate, link)
|
||||
// Update each link in chanPolicies.
|
||||
for targetLink := range chanPolicies {
|
||||
cid := lnwire.NewChanIDFromOutPoint(&targetLink)
|
||||
|
||||
link, ok := s.linkIndex[cid]
|
||||
if !ok {
|
||||
log.Debugf("Unable to find ChannelPoint(%v) to update "+
|
||||
"link policy", targetLink)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
// Otherwise, we'll only attempt to update the forwarding
|
||||
// policies for the set of targeted links.
|
||||
for _, targetLink := range targetChans {
|
||||
cid := lnwire.NewChanIDFromOutPoint(&targetLink)
|
||||
|
||||
// If we can't locate a link by its converted channel
|
||||
// ID, then we'll return an error back to the caller.
|
||||
link, ok := s.linkIndex[cid]
|
||||
if !ok {
|
||||
s.indexMtx.RUnlock()
|
||||
|
||||
return fmt.Errorf("unable to find "+
|
||||
"ChannelPoint(%v) to update link "+
|
||||
"policy", targetLink)
|
||||
}
|
||||
|
||||
linksToUpdate = append(linksToUpdate, link)
|
||||
}
|
||||
}
|
||||
|
||||
s.indexMtx.RUnlock()
|
||||
|
||||
// With all the links we need to update collected, we can release the
|
||||
// mutex then update each link directly.
|
||||
for _, link := range linksToUpdate {
|
||||
newPolicy := dbPolicyToFwdingPolicy(
|
||||
chanPolicies[*link.ChannelPoint()],
|
||||
)
|
||||
link.UpdateForwardingPolicy(newPolicy)
|
||||
}
|
||||
|
||||
return nil
|
||||
s.indexMtx.RUnlock()
|
||||
}
|
||||
|
||||
// dbPolicyToFwdingPolicy is a helper function that converts a channeldb
|
||||
// ChannelEdgePolicy into a ForwardingPolicy struct for the purpose of updating
|
||||
// the forwarding policy of a link.
|
||||
func dbPolicyToFwdingPolicy(policy *channeldb.ChannelEdgePolicy) ForwardingPolicy {
|
||||
return ForwardingPolicy{
|
||||
BaseFee: policy.FeeBaseMSat,
|
||||
FeeRate: policy.FeeProportionalMillionths,
|
||||
TimeLockDelta: uint32(policy.TimeLockDelta),
|
||||
MinHTLC: policy.MinHTLC,
|
||||
MaxHTLC: policy.MaxHTLC,
|
||||
}
|
||||
}
|
||||
|
||||
// forward is used in order to find next channel link and apply htlc update.
|
||||
|
||||
Reference in new issue
Block a user