2019-09-19 11:02:46 +02:00
|
|
|
package localchans
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
2021-08-23 12:16:37 +02:00
|
|
|
"github.com/lightningnetwork/lnd/kvdb"
|
2019-09-19 11:02:46 +02:00
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
|
|
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
|
|
"github.com/btcsuite/btcutil"
|
|
|
|
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
|
|
"github.com/lightningnetwork/lnd/channeldb"
|
|
|
|
"github.com/lightningnetwork/lnd/discovery"
|
|
|
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
|
|
|
"github.com/lightningnetwork/lnd/routing"
|
|
|
|
)
|
|
|
|
|
|
|
|
// TestManager tests that the local channel manager properly propagates fee
|
|
|
|
// updates to gossiper and links.
|
|
|
|
func TestManager(t *testing.T) {
|
2019-08-20 02:53:21 +02:00
|
|
|
var (
|
|
|
|
chanPoint = wire.OutPoint{Hash: chainhash.Hash{1}, Index: 2}
|
|
|
|
chanCap = btcutil.Amount(1000)
|
|
|
|
maxPendingAmount = lnwire.MilliSatoshi(999000)
|
|
|
|
minHTLC = lnwire.MilliSatoshi(2000)
|
|
|
|
)
|
2019-09-19 11:02:46 +02:00
|
|
|
|
|
|
|
newPolicy := routing.ChannelPolicy{
|
|
|
|
FeeSchema: routing.FeeSchema{
|
|
|
|
BaseFee: 100,
|
|
|
|
FeeRate: 200,
|
|
|
|
},
|
|
|
|
TimeLockDelta: 80,
|
2019-08-20 02:53:21 +02:00
|
|
|
MaxHTLC: 5000,
|
|
|
|
}
|
|
|
|
|
|
|
|
currentPolicy := channeldb.ChannelEdgePolicy{
|
|
|
|
MinHTLC: minHTLC,
|
|
|
|
MessageFlags: lnwire.ChanUpdateOptionMaxHtlc,
|
2019-09-19 11:02:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
updateForwardingPolicies := func(
|
|
|
|
chanPolicies map[wire.OutPoint]htlcswitch.ForwardingPolicy) {
|
|
|
|
|
|
|
|
if len(chanPolicies) != 1 {
|
|
|
|
t.Fatal("unexpected number of policies to apply")
|
|
|
|
}
|
|
|
|
|
|
|
|
policy := chanPolicies[chanPoint]
|
|
|
|
if policy.TimeLockDelta != newPolicy.TimeLockDelta {
|
|
|
|
t.Fatal("unexpected time lock delta")
|
|
|
|
}
|
|
|
|
if policy.BaseFee != newPolicy.BaseFee {
|
|
|
|
t.Fatal("unexpected base fee")
|
|
|
|
}
|
|
|
|
if uint32(policy.FeeRate) != newPolicy.FeeRate {
|
|
|
|
t.Fatal("unexpected base fee")
|
|
|
|
}
|
2019-08-20 02:53:21 +02:00
|
|
|
if policy.MaxHTLC != newPolicy.MaxHTLC {
|
2019-09-19 11:02:46 +02:00
|
|
|
t.Fatal("unexpected max htlc")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
propagateChanPolicyUpdate := func(
|
|
|
|
edgesToUpdate []discovery.EdgeWithInfo) error {
|
|
|
|
|
|
|
|
if len(edgesToUpdate) != 1 {
|
|
|
|
t.Fatal("unexpected number of edges to update")
|
|
|
|
}
|
|
|
|
|
|
|
|
policy := edgesToUpdate[0].Edge
|
|
|
|
if !policy.MessageFlags.HasMaxHtlc() {
|
|
|
|
t.Fatal("expected max htlc flag")
|
|
|
|
}
|
|
|
|
if policy.TimeLockDelta != uint16(newPolicy.TimeLockDelta) {
|
|
|
|
t.Fatal("unexpected time lock delta")
|
|
|
|
}
|
|
|
|
if policy.FeeBaseMSat != newPolicy.BaseFee {
|
|
|
|
t.Fatal("unexpected base fee")
|
|
|
|
}
|
|
|
|
if uint32(policy.FeeProportionalMillionths) != newPolicy.FeeRate {
|
|
|
|
t.Fatal("unexpected base fee")
|
|
|
|
}
|
2019-08-20 02:53:21 +02:00
|
|
|
if policy.MaxHTLC != newPolicy.MaxHTLC {
|
2019-09-19 11:02:46 +02:00
|
|
|
t.Fatal("unexpected max htlc")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-08-23 12:16:37 +02:00
|
|
|
forAllOutgoingChannels := func(cb func(kvdb.RTx,
|
|
|
|
*channeldb.ChannelEdgeInfo,
|
2019-09-19 11:02:46 +02:00
|
|
|
*channeldb.ChannelEdgePolicy) error) error {
|
|
|
|
|
|
|
|
return cb(
|
2021-08-23 12:16:37 +02:00
|
|
|
nil,
|
2019-09-19 11:02:46 +02:00
|
|
|
&channeldb.ChannelEdgeInfo{
|
|
|
|
Capacity: chanCap,
|
|
|
|
ChannelPoint: chanPoint,
|
|
|
|
},
|
2019-08-20 02:53:21 +02:00
|
|
|
¤tPolicy,
|
2019-09-19 11:02:46 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-08-23 12:16:37 +02:00
|
|
|
fetchChannel := func(tx kvdb.RTx, chanPoint wire.OutPoint) (
|
|
|
|
*channeldb.OpenChannel, error) {
|
2019-08-20 02:53:21 +02:00
|
|
|
|
|
|
|
constraints := channeldb.ChannelConstraints{
|
|
|
|
MaxPendingAmount: maxPendingAmount,
|
|
|
|
MinHTLC: minHTLC,
|
|
|
|
}
|
|
|
|
|
|
|
|
return &channeldb.OpenChannel{
|
|
|
|
LocalChanCfg: channeldb.ChannelConfig{
|
|
|
|
ChannelConstraints: constraints,
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2019-09-19 11:02:46 +02:00
|
|
|
manager := Manager{
|
|
|
|
UpdateForwardingPolicies: updateForwardingPolicies,
|
|
|
|
PropagateChanPolicyUpdate: propagateChanPolicyUpdate,
|
|
|
|
ForAllOutgoingChannels: forAllOutgoingChannels,
|
2019-08-20 02:53:21 +02:00
|
|
|
FetchChannel: fetchChannel,
|
2019-09-19 11:02:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Test updating a specific channels.
|
|
|
|
err := manager.UpdatePolicy(newPolicy, chanPoint)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test updating all channels, which comes down to the same as testing a
|
|
|
|
// specific channel because there is only one channel.
|
|
|
|
err = manager.UpdatePolicy(newPolicy)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2019-08-20 02:53:21 +02:00
|
|
|
|
|
|
|
// If no max htlc is specified, the max htlc value should be kept
|
|
|
|
// unchanged.
|
|
|
|
currentPolicy.MaxHTLC = newPolicy.MaxHTLC
|
|
|
|
noMaxHtlcPolicy := newPolicy
|
|
|
|
noMaxHtlcPolicy.MaxHTLC = 0
|
|
|
|
|
|
|
|
err = manager.UpdatePolicy(noMaxHtlcPolicy)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2019-09-19 11:02:46 +02:00
|
|
|
}
|