funding: make sure initial policy is always set
This commit is contained in:
1 parent
d5c504c8de
commit
7ac445caaf
2 files changed
+111
-32
No files matched your search
@@ -3711,6 +3711,13 @@ func (f *Manager) handleChannelReady(peer lnpeer.Peer,
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// Before we can add the channel to the peer, we'll need to ensure that
|
||||||
|
// we have an initial forwarding policy set.
|
||||||
|
if err := f.ensureInitialForwardingPolicy(chanID, channel); err != nil {
|
||||||
|
log.Errorf("Unable to ensure initial forwarding policy: %v",
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := peer.AddNewChannel(channel, f.quit); err != nil {
|
if err := peer.AddNewChannel(channel, f.quit); err != nil {
|
||||||
log.Errorf("Unable to add new channel %v with peer %x: %v",
|
log.Errorf("Unable to add new channel %v with peer %x: %v",
|
||||||
channel.FundingOutpoint,
|
channel.FundingOutpoint,
|
||||||
@@ -3719,6 +3726,54 @@ func (f *Manager) handleChannelReady(peer lnpeer.Peer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensureInitialForwardingPolicy ensures that we have an initial forwarding
|
||||||
|
// policy set for the given channel. If we don't, we'll fall back to the default
|
||||||
|
// values.
|
||||||
|
func (f *Manager) ensureInitialForwardingPolicy(chanID lnwire.ChannelID,
|
||||||
|
channel *channeldb.OpenChannel) error {
|
||||||
|
|
||||||
|
// Before we can add the channel to the peer, we'll need to ensure that
|
||||||
|
// we have an initial forwarding policy set. This should always be the
|
||||||
|
// case except for a channel that was created with lnd <= 0.15.5 and
|
||||||
|
// is still pending while updating to this version.
|
||||||
|
var needDBUpdate bool
|
||||||
|
forwardingPolicy, err := f.getInitialForwardingPolicy(chanID)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unable to fetch initial forwarding policy, "+
|
||||||
|
"falling back to default values: %v", err)
|
||||||
|
|
||||||
|
forwardingPolicy = f.defaultForwardingPolicy(
|
||||||
|
channel.LocalChanCfg.ChannelConstraints,
|
||||||
|
)
|
||||||
|
needDBUpdate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only started storing the actual values for MinHTLCOut and MaxHTLC
|
||||||
|
// after 0.16.x, so if a channel was opened with such a version and is
|
||||||
|
// still pending while updating to this version, we'll need to set the
|
||||||
|
// values to the default values.
|
||||||
|
if forwardingPolicy.MinHTLCOut == 0 {
|
||||||
|
forwardingPolicy.MinHTLCOut = channel.LocalChanCfg.MinHTLC
|
||||||
|
needDBUpdate = true
|
||||||
|
}
|
||||||
|
if forwardingPolicy.MaxHTLC == 0 {
|
||||||
|
forwardingPolicy.MaxHTLC = channel.LocalChanCfg.MaxPendingAmount
|
||||||
|
needDBUpdate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// And finally, if we found that the values currently stored aren't
|
||||||
|
// sufficient for the link, we'll update the database.
|
||||||
|
if needDBUpdate {
|
||||||
|
err := f.saveInitialForwardingPolicy(chanID, forwardingPolicy)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to update initial "+
|
||||||
|
"forwarding policy: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// chanAnnouncement encapsulates the two authenticated announcements that we
|
// chanAnnouncement encapsulates the two authenticated announcements that we
|
||||||
// send out to the network after a new channel has been created locally.
|
// send out to the network after a new channel has been created locally.
|
||||||
type chanAnnouncement struct {
|
type chanAnnouncement struct {
|
||||||
|
|||||||
+56
-32
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -31,6 +32,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnpeer"
|
"github.com/lightningnetwork/lnd/lnpeer"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest/mock"
|
"github.com/lightningnetwork/lnd/lntest/mock"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@@ -1340,42 +1342,38 @@ func assertInitialFwdingPolicyNotFound(t *testing.T, node *testNode,
|
|||||||
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
var fwdingPolicy *models.ForwardingPolicy
|
_, err := node.fundingMgr.getInitialForwardingPolicy(*chanID)
|
||||||
var err error
|
|
||||||
for i := 0; i < testPollNumTries; i++ {
|
|
||||||
// If this is not the first try, sleep before retrying.
|
|
||||||
if i > 0 {
|
|
||||||
time.Sleep(testPollSleepMs * time.Millisecond)
|
|
||||||
}
|
|
||||||
fwdingPolicy, err = node.fundingMgr.getInitialForwardingPolicy(
|
|
||||||
*chanID,
|
|
||||||
)
|
|
||||||
require.ErrorIs(t, err, channeldb.ErrChannelNotFound)
|
require.ErrorIs(t, err, channeldb.ErrChannelNotFound)
|
||||||
|
|
||||||
// Got expected result, return with success.
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10 tries without success.
|
func assertHandleChannelReady(t *testing.T, alice, bob *testNode,
|
||||||
t.Fatalf("expected to not find a forwarding policy, found policy %v",
|
checkChannel ...func(node *testNode, msg *newChannelMsg) bool) {
|
||||||
fwdingPolicy)
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertHandleChannelReady(t *testing.T, alice, bob *testNode) {
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
const timeout = time.Second * 15
|
||||||
// They should both send the new channel state to their peer.
|
// They should both send the new channel state to their peer.
|
||||||
select {
|
select {
|
||||||
case c := <-alice.newChannels:
|
case c := <-alice.newChannels:
|
||||||
|
for _, check := range checkChannel {
|
||||||
|
require.NoError(t, wait.Predicate(func() bool {
|
||||||
|
return check(alice, c)
|
||||||
|
}, timeout))
|
||||||
|
}
|
||||||
close(c.err)
|
close(c.err)
|
||||||
case <-time.After(time.Second * 15):
|
case <-time.After(timeout):
|
||||||
t.Fatalf("alice did not send new channel to peer")
|
t.Fatalf("alice did not send new channel to peer")
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case c := <-bob.newChannels:
|
case c := <-bob.newChannels:
|
||||||
|
for _, check := range checkChannel {
|
||||||
|
require.NoError(t, wait.Predicate(func() bool {
|
||||||
|
return check(bob, c)
|
||||||
|
}, timeout))
|
||||||
|
}
|
||||||
close(c.err)
|
close(c.err)
|
||||||
case <-time.After(time.Second * 15):
|
case <-time.After(timeout):
|
||||||
t.Fatalf("bob did not send new channel to peer")
|
t.Fatalf("bob did not send new channel to peer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2892,12 +2890,12 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
|||||||
const fundingAmt = 5000000
|
const fundingAmt = 5000000
|
||||||
const chanReserve = 100000
|
const chanReserve = 100000
|
||||||
|
|
||||||
// Use custom channel fees.
|
// Use custom channel fees. These will show up in the channel
|
||||||
// These will show up in the channel reservation context
|
// reservation context.
|
||||||
var baseFee uint64
|
var (
|
||||||
var feeRate uint64
|
baseFee uint64 = 42
|
||||||
baseFee = 42
|
feeRate uint64 = 1337
|
||||||
feeRate = 1337
|
)
|
||||||
|
|
||||||
// We will consume the channel updates as we go, so no buffering is
|
// We will consume the channel updates as we go, so no buffering is
|
||||||
// needed.
|
// needed.
|
||||||
@@ -3218,10 +3216,6 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
|||||||
alice.fundingMgr.ProcessFundingMsg(channelReadyBob, bob)
|
alice.fundingMgr.ProcessFundingMsg(channelReadyBob, bob)
|
||||||
bob.fundingMgr.ProcessFundingMsg(channelReadyAlice, alice)
|
bob.fundingMgr.ProcessFundingMsg(channelReadyAlice, alice)
|
||||||
|
|
||||||
// Check that they notify the breach arbiter and peer about the new
|
|
||||||
// channel.
|
|
||||||
assertHandleChannelReady(t, alice, bob)
|
|
||||||
|
|
||||||
// Make sure both fundingManagers send the expected channel
|
// Make sure both fundingManagers send the expected channel
|
||||||
// announcements.
|
// announcements.
|
||||||
// Alice should advertise the default MinHTLC value of
|
// Alice should advertise the default MinHTLC value of
|
||||||
@@ -3238,15 +3232,45 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
|||||||
|
|
||||||
// Alice should have custom fees set whereas Bob should see his
|
// Alice should have custom fees set whereas Bob should see his
|
||||||
// configured default fees announced.
|
// configured default fees announced.
|
||||||
|
defaultDelta := bob.fundingMgr.cfg.DefaultRoutingPolicy.TimeLockDelta
|
||||||
defaultBaseFee := bob.fundingMgr.cfg.DefaultRoutingPolicy.BaseFee
|
defaultBaseFee := bob.fundingMgr.cfg.DefaultRoutingPolicy.BaseFee
|
||||||
defaultFeerate := bob.fundingMgr.cfg.DefaultRoutingPolicy.FeeRate
|
defaultFeeRate := bob.fundingMgr.cfg.DefaultRoutingPolicy.FeeRate
|
||||||
baseFees := []lnwire.MilliSatoshi{
|
baseFees := []lnwire.MilliSatoshi{
|
||||||
lnwire.MilliSatoshi(baseFee), defaultBaseFee,
|
lnwire.MilliSatoshi(baseFee), defaultBaseFee,
|
||||||
}
|
}
|
||||||
feeRates := []lnwire.MilliSatoshi{
|
feeRates := []lnwire.MilliSatoshi{
|
||||||
lnwire.MilliSatoshi(feeRate), defaultFeerate,
|
lnwire.MilliSatoshi(feeRate), defaultFeeRate,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that they notify the breach arbiter and peer about the new
|
||||||
|
// channel.
|
||||||
|
assertHandleChannelReady(
|
||||||
|
t, alice, bob, func(node *testNode, msg *newChannelMsg) bool {
|
||||||
|
aliceDB := alice.fundingMgr.cfg.ChannelDB
|
||||||
|
chanID := lnwire.NewChanIDFromOutPoint(
|
||||||
|
&msg.channel.FundingOutpoint,
|
||||||
|
)
|
||||||
|
|
||||||
|
if node == alice {
|
||||||
|
p, err := aliceDB.GetInitialForwardingPolicy(
|
||||||
|
chanID,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return reflect.DeepEqual(
|
||||||
|
p, &models.ForwardingPolicy{
|
||||||
|
MaxHTLC: maxHtlcArr[0],
|
||||||
|
MinHTLCOut: minHtlcArr[0],
|
||||||
|
BaseFee: baseFees[0],
|
||||||
|
FeeRate: feeRates[0],
|
||||||
|
TimeLockDelta: defaultDelta,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
)
|
||||||
assertChannelAnnouncements(
|
assertChannelAnnouncements(
|
||||||
t, alice, bob, capacity, minHtlcArr, maxHtlcArr, baseFees,
|
t, alice, bob, capacity, minHtlcArr, maxHtlcArr, baseFees,
|
||||||
feeRates,
|
feeRates,
|
||||||
|
|||||||
Reference in new issue
Block a user