mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
Merge pull request #3697 from joostjager/lower-min-htlc
config: improve management of htlc amount lower limit
This commit is contained in:
commit
70c5fe3d00
@ -36,7 +36,22 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultBitcoinMinHTLCMSat = lnwire.MilliSatoshi(1000)
|
||||
// defaultBitcoinMinHTLCMSat is the default smallest value htlc this
|
||||
// node will accept. This value is proposed in the channel open sequence
|
||||
// and cannot be changed during the life of the channel. It is zero by
|
||||
// default to allow maximum flexibility in deciding what size payments
|
||||
// to forward.
|
||||
//
|
||||
// All forwarded payments are subjected to the min htlc constraint of
|
||||
// the routing policy of the outgoing channel. This implicitly controls
|
||||
// the minimum htlc value on the incoming channel too.
|
||||
defaultBitcoinMinHTLCInMSat = lnwire.MilliSatoshi(1)
|
||||
|
||||
// defaultBitcoinMinHTLCOutMSat is the default minimum htlc value that
|
||||
// we require for sending out htlcs. Our channel peer may have a lower
|
||||
// min htlc channel parameter, but we - by default - don't forward
|
||||
// anything under the value defined here.
|
||||
defaultBitcoinMinHTLCOutMSat = lnwire.MilliSatoshi(1000)
|
||||
|
||||
// DefaultBitcoinBaseFeeMSat is the default forwarding base fee.
|
||||
DefaultBitcoinBaseFeeMSat = lnwire.MilliSatoshi(1000)
|
||||
@ -48,11 +63,12 @@ const (
|
||||
// delta.
|
||||
DefaultBitcoinTimeLockDelta = 40
|
||||
|
||||
defaultLitecoinMinHTLCMSat = lnwire.MilliSatoshi(1000)
|
||||
defaultLitecoinBaseFeeMSat = lnwire.MilliSatoshi(1000)
|
||||
defaultLitecoinFeeRate = lnwire.MilliSatoshi(1)
|
||||
defaultLitecoinTimeLockDelta = 576
|
||||
defaultLitecoinDustLimit = btcutil.Amount(54600)
|
||||
defaultLitecoinMinHTLCInMSat = lnwire.MilliSatoshi(1)
|
||||
defaultLitecoinMinHTLCOutMSat = lnwire.MilliSatoshi(1000)
|
||||
defaultLitecoinBaseFeeMSat = lnwire.MilliSatoshi(1000)
|
||||
defaultLitecoinFeeRate = lnwire.MilliSatoshi(1)
|
||||
defaultLitecoinTimeLockDelta = 576
|
||||
defaultLitecoinDustLimit = btcutil.Amount(54600)
|
||||
|
||||
// defaultBitcoinStaticFeePerKW is the fee rate of 50 sat/vbyte
|
||||
// expressed in sat/kw.
|
||||
@ -130,6 +146,8 @@ type chainControl struct {
|
||||
wallet *lnwallet.LightningWallet
|
||||
|
||||
routingPolicy htlcswitch.ForwardingPolicy
|
||||
|
||||
minHtlcIn lnwire.MilliSatoshi
|
||||
}
|
||||
|
||||
// newChainControlFromConfig attempts to create a chainControl instance
|
||||
@ -157,21 +175,23 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
||||
switch registeredChains.PrimaryChain() {
|
||||
case bitcoinChain:
|
||||
cc.routingPolicy = htlcswitch.ForwardingPolicy{
|
||||
MinHTLC: cfg.Bitcoin.MinHTLC,
|
||||
MinHTLCOut: cfg.Bitcoin.MinHTLCOut,
|
||||
BaseFee: cfg.Bitcoin.BaseFee,
|
||||
FeeRate: cfg.Bitcoin.FeeRate,
|
||||
TimeLockDelta: cfg.Bitcoin.TimeLockDelta,
|
||||
}
|
||||
cc.minHtlcIn = cfg.Bitcoin.MinHTLCIn
|
||||
cc.feeEstimator = chainfee.NewStaticEstimator(
|
||||
defaultBitcoinStaticFeePerKW, 0,
|
||||
)
|
||||
case litecoinChain:
|
||||
cc.routingPolicy = htlcswitch.ForwardingPolicy{
|
||||
MinHTLC: cfg.Litecoin.MinHTLC,
|
||||
MinHTLCOut: cfg.Litecoin.MinHTLCOut,
|
||||
BaseFee: cfg.Litecoin.BaseFee,
|
||||
FeeRate: cfg.Litecoin.FeeRate,
|
||||
TimeLockDelta: cfg.Litecoin.TimeLockDelta,
|
||||
}
|
||||
cc.minHtlcIn = cfg.Litecoin.MinHTLCIn
|
||||
cc.feeEstimator = chainfee.NewStaticEstimator(
|
||||
defaultLitecoinStaticFeePerKW, 0,
|
||||
)
|
||||
|
@ -2767,11 +2767,11 @@ type ChannelEdgePolicy struct {
|
||||
// the node would like to HTLC exchanges.
|
||||
TimeLockDelta uint16
|
||||
|
||||
// MinHTLC is the smallest value HTLC this node will accept, expressed
|
||||
// MinHTLC is the smallest value HTLC this node will forward, expressed
|
||||
// in millisatoshi.
|
||||
MinHTLC lnwire.MilliSatoshi
|
||||
|
||||
// MaxHTLC is the largest value HTLC this node will accept, expressed
|
||||
// MaxHTLC is the largest value HTLC this node will forward, expressed
|
||||
// in millisatoshi.
|
||||
MaxHTLC lnwire.MilliSatoshi
|
||||
|
||||
|
@ -3459,6 +3459,12 @@ var updateChannelPolicyCommand = cli.Command{
|
||||
Usage: "the CLTV delta that will be applied to all " +
|
||||
"forwarded HTLCs",
|
||||
},
|
||||
cli.Uint64Flag{
|
||||
Name: "min_htlc_msat",
|
||||
Usage: "if set, the min HTLC size that will be applied " +
|
||||
"to all forwarded HTLCs. If unset, the min HTLC " +
|
||||
"is left unchanged.",
|
||||
},
|
||||
cli.Uint64Flag{
|
||||
Name: "max_htlc_msat",
|
||||
Usage: "if set, the max HTLC size that will be applied " +
|
||||
@ -3581,6 +3587,11 @@ func updateChannelPolicy(ctx *cli.Context) error {
|
||||
MaxHtlcMsat: ctx.Uint64("max_htlc_msat"),
|
||||
}
|
||||
|
||||
if ctx.IsSet("min_htlc_msat") {
|
||||
req.MinHtlcMsat = ctx.Uint64("min_htlc_msat")
|
||||
req.MinHtlcMsatSpecified = true
|
||||
}
|
||||
|
||||
if chanPoint != nil {
|
||||
req.Scope = &lnrpc.PolicyUpdateRequest_ChanPoint{
|
||||
ChanPoint: chanPoint,
|
||||
|
@ -166,7 +166,8 @@ type chainConfig struct {
|
||||
|
||||
DefaultNumChanConfs int `long:"defaultchanconfs" description:"The default number of confirmations a channel must have before it's considered open. If this is not set, we will scale the value according to the channel size."`
|
||||
DefaultRemoteDelay int `long:"defaultremotedelay" description:"The default number of blocks we will require our channel counterparty to wait before accessing its funds in case of unilateral close. If this is not set, we will scale the value according to the channel size."`
|
||||
MinHTLC lnwire.MilliSatoshi `long:"minhtlc" description:"The smallest HTLC we are willing to forward on our channels, in millisatoshi"`
|
||||
MinHTLCIn lnwire.MilliSatoshi `long:"minhtlc" description:"The smallest HTLC we are willing to accept on our channels, in millisatoshi"`
|
||||
MinHTLCOut lnwire.MilliSatoshi `long:"minhtlcout" description:"The smallest HTLC we are willing to send out on our channels, in millisatoshi"`
|
||||
BaseFee lnwire.MilliSatoshi `long:"basefee" description:"The base fee in millisatoshi we will charge for forwarding payments on our channels"`
|
||||
FeeRate lnwire.MilliSatoshi `long:"feerate" description:"The fee rate used when forwarding payments on our channels. The total fee charged is basefee + (amount * feerate / 1000000), where amount is the forwarded amount."`
|
||||
TimeLockDelta uint32 `long:"timelockdelta" description:"The CLTV delta we will subtract from a forwarded HTLC's timelock value"`
|
||||
@ -360,7 +361,8 @@ func loadConfig() (*config, error) {
|
||||
MaxLogFiles: defaultMaxLogFiles,
|
||||
MaxLogFileSize: defaultMaxLogFileSize,
|
||||
Bitcoin: &chainConfig{
|
||||
MinHTLC: defaultBitcoinMinHTLCMSat,
|
||||
MinHTLCIn: defaultBitcoinMinHTLCInMSat,
|
||||
MinHTLCOut: defaultBitcoinMinHTLCOutMSat,
|
||||
BaseFee: DefaultBitcoinBaseFeeMSat,
|
||||
FeeRate: DefaultBitcoinFeeRate,
|
||||
TimeLockDelta: DefaultBitcoinTimeLockDelta,
|
||||
@ -376,7 +378,8 @@ func loadConfig() (*config, error) {
|
||||
RPCHost: defaultRPCHost,
|
||||
},
|
||||
Litecoin: &chainConfig{
|
||||
MinHTLC: defaultLitecoinMinHTLCMSat,
|
||||
MinHTLCIn: defaultLitecoinMinHTLCInMSat,
|
||||
MinHTLCOut: defaultLitecoinMinHTLCOutMSat,
|
||||
BaseFee: defaultLitecoinBaseFeeMSat,
|
||||
FeeRate: defaultLitecoinFeeRate,
|
||||
TimeLockDelta: defaultLitecoinTimeLockDelta,
|
||||
|
@ -285,6 +285,10 @@ type fundingConfig struct {
|
||||
// initially announcing channels.
|
||||
DefaultRoutingPolicy htlcswitch.ForwardingPolicy
|
||||
|
||||
// DefaultMinHtlcIn is the default minimum incoming htlc value that is
|
||||
// set as a channel parameter.
|
||||
DefaultMinHtlcIn lnwire.MilliSatoshi
|
||||
|
||||
// NumRequiredConfs is a function closure that helps the funding
|
||||
// manager decide how many confirmations it should require for a
|
||||
// channel extended to it. The function is able to take into account
|
||||
@ -1300,7 +1304,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
|
||||
chanReserve := f.cfg.RequiredRemoteChanReserve(amt, msg.DustLimit)
|
||||
maxValue := f.cfg.RequiredRemoteMaxValue(amt)
|
||||
maxHtlcs := f.cfg.RequiredRemoteMaxHTLCs(amt)
|
||||
minHtlc := f.cfg.DefaultRoutingPolicy.MinHTLC
|
||||
minHtlc := f.cfg.DefaultMinHtlcIn
|
||||
|
||||
// Once the reservation has been created successfully, we add it to
|
||||
// this peer's map of pending reservations to track this particular
|
||||
@ -2205,6 +2209,12 @@ func (f *fundingManager) addToRouterGraph(completeChan *channeldb.OpenChannel,
|
||||
// need to determine the smallest HTLC it deems economically relevant.
|
||||
fwdMinHTLC := completeChan.LocalChanCfg.MinHTLC
|
||||
|
||||
// We don't necessarily want to go as low as the remote party
|
||||
// allows. Check it against our default forwarding policy.
|
||||
if fwdMinHTLC < f.cfg.DefaultRoutingPolicy.MinHTLCOut {
|
||||
fwdMinHTLC = f.cfg.DefaultRoutingPolicy.MinHTLCOut
|
||||
}
|
||||
|
||||
// We'll obtain the max HTLC value we can forward in our direction, as
|
||||
// we'll use this value within our ChannelUpdate. This value must be <=
|
||||
// channel capacity and <= the maximum in-flight msats set by the peer.
|
||||
@ -2375,30 +2385,13 @@ func (f *fundingManager) annAfterSixConfs(completeChan *channeldb.OpenChannel,
|
||||
fndgLog.Infof("Announcing ChannelPoint(%v), short_chan_id=%v",
|
||||
&fundingPoint, shortChanID)
|
||||
|
||||
// We'll obtain the min HTLC value we can forward in our
|
||||
// direction, as we'll use this value within our ChannelUpdate.
|
||||
// This constraint is originally set by the remote node, as it
|
||||
// will be the one that will need to determine the smallest
|
||||
// HTLC it deems economically relevant.
|
||||
fwdMinHTLC := completeChan.LocalChanCfg.MinHTLC
|
||||
|
||||
// We'll obtain the max HTLC value we can forward in our
|
||||
// direction, as we'll use this value within our ChannelUpdate.
|
||||
// This value must be <= channel capacity and <= the maximum
|
||||
// in-flight msats set by the peer.
|
||||
fwdMaxHTLC := completeChan.LocalChanCfg.MaxPendingAmount
|
||||
capacityMSat := lnwire.NewMSatFromSatoshis(completeChan.Capacity)
|
||||
if fwdMaxHTLC > capacityMSat {
|
||||
fwdMaxHTLC = capacityMSat
|
||||
}
|
||||
|
||||
// Create and broadcast the proofs required to make this channel
|
||||
// public and usable for other nodes for routing.
|
||||
err = f.announceChannel(
|
||||
f.cfg.IDKey, completeChan.IdentityPub,
|
||||
completeChan.LocalChanCfg.MultiSigKey.PubKey,
|
||||
completeChan.RemoteChanCfg.MultiSigKey.PubKey,
|
||||
*shortChanID, chanID, fwdMinHTLC, fwdMaxHTLC,
|
||||
*shortChanID, chanID,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("channel announcement failed: %v", err)
|
||||
@ -2690,15 +2683,18 @@ func (f *fundingManager) newChanAnnouncement(localPubKey, remotePubKey,
|
||||
// finish, either successfully or with an error.
|
||||
func (f *fundingManager) announceChannel(localIDKey, remoteIDKey, localFundingKey,
|
||||
remoteFundingKey *btcec.PublicKey, shortChanID lnwire.ShortChannelID,
|
||||
chanID lnwire.ChannelID, fwdMinHTLC, fwdMaxHTLC lnwire.MilliSatoshi) error {
|
||||
chanID lnwire.ChannelID) error {
|
||||
|
||||
// First, we'll create the batch of announcements to be sent upon
|
||||
// initial channel creation. This includes the channel announcement
|
||||
// itself, the channel update announcement, and our half of the channel
|
||||
// proof needed to fully authenticate the channel.
|
||||
//
|
||||
// We can pass in zeroes for the min and max htlc policy, because we
|
||||
// only use the channel announcement message from the returned struct.
|
||||
ann, err := f.newChanAnnouncement(localIDKey, remoteIDKey,
|
||||
localFundingKey, remoteFundingKey, shortChanID, chanID,
|
||||
fwdMinHTLC, fwdMaxHTLC,
|
||||
0, 0,
|
||||
)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("can't generate channel announcement: %v", err)
|
||||
@ -2820,7 +2816,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
||||
var (
|
||||
peerKey = msg.peer.IdentityKey()
|
||||
localAmt = msg.localFundingAmt
|
||||
minHtlc = msg.minHtlc
|
||||
minHtlcIn = msg.minHtlcIn
|
||||
remoteCsvDelay = msg.remoteCsvDelay
|
||||
)
|
||||
|
||||
@ -2936,8 +2932,8 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
||||
}
|
||||
|
||||
// If no minimum HTLC value was specified, use the default one.
|
||||
if minHtlc == 0 {
|
||||
minHtlc = f.cfg.DefaultRoutingPolicy.MinHTLC
|
||||
if minHtlcIn == 0 {
|
||||
minHtlcIn = f.cfg.DefaultMinHtlcIn
|
||||
}
|
||||
|
||||
// If a pending channel map for this peer isn't already created, then
|
||||
@ -2952,7 +2948,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
||||
resCtx := &reservationWithCtx{
|
||||
chanAmt: capacity,
|
||||
remoteCsvDelay: remoteCsvDelay,
|
||||
remoteMinHtlc: minHtlc,
|
||||
remoteMinHtlc: minHtlcIn,
|
||||
reservation: reservation,
|
||||
peer: msg.peer,
|
||||
updates: msg.updates,
|
||||
@ -2986,7 +2982,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
||||
DustLimit: ourContribution.DustLimit,
|
||||
MaxValueInFlight: maxValue,
|
||||
ChannelReserve: chanReserve,
|
||||
HtlcMinimum: minHtlc,
|
||||
HtlcMinimum: minHtlcIn,
|
||||
FeePerKiloWeight: uint32(commitFeePerKw),
|
||||
CsvDelay: remoteCsvDelay,
|
||||
MaxAcceptedHTLCs: maxHtlcs,
|
||||
|
@ -336,11 +336,12 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
|
||||
return nil, fmt.Errorf("unable to find channel")
|
||||
},
|
||||
DefaultRoutingPolicy: htlcswitch.ForwardingPolicy{
|
||||
MinHTLC: 5,
|
||||
MinHTLCOut: 5,
|
||||
BaseFee: 100,
|
||||
FeeRate: 1000,
|
||||
TimeLockDelta: 10,
|
||||
},
|
||||
DefaultMinHtlcIn: 5,
|
||||
NumRequiredConfs: func(chanAmt btcutil.Amount,
|
||||
pushAmt lnwire.MilliSatoshi) uint16 {
|
||||
return 3
|
||||
@ -464,11 +465,12 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) {
|
||||
TempChanIDSeed: oldCfg.TempChanIDSeed,
|
||||
FindChannel: oldCfg.FindChannel,
|
||||
DefaultRoutingPolicy: htlcswitch.ForwardingPolicy{
|
||||
MinHTLC: 5,
|
||||
MinHTLCOut: 5,
|
||||
BaseFee: 100,
|
||||
FeeRate: 1000,
|
||||
TimeLockDelta: 10,
|
||||
},
|
||||
DefaultMinHtlcIn: 5,
|
||||
RequiredRemoteMaxValue: oldCfg.RequiredRemoteMaxValue,
|
||||
PublishTransaction: func(txn *wire.MsgTx) error {
|
||||
publishChan <- txn
|
||||
@ -926,7 +928,7 @@ func assertChannelAnnouncements(t *testing.T, alice, bob *testNode,
|
||||
// _other_ node.
|
||||
other := (j + 1) % 2
|
||||
minHtlc := nodes[other].fundingMgr.cfg.
|
||||
DefaultRoutingPolicy.MinHTLC
|
||||
DefaultMinHtlcIn
|
||||
|
||||
// We might expect a custom MinHTLC value.
|
||||
if len(customMinHtlc) > 0 {
|
||||
@ -2325,7 +2327,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
||||
|
||||
// This is the custom parameters we'll use.
|
||||
const csvDelay = 67
|
||||
const minHtlc = 1234
|
||||
const minHtlcIn = 1234
|
||||
|
||||
// We will consume the channel updates as we go, so no buffering is
|
||||
// needed.
|
||||
@ -2344,7 +2346,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
||||
localFundingAmt: localAmt,
|
||||
pushAmt: lnwire.NewMSatFromSatoshis(pushAmt),
|
||||
private: false,
|
||||
minHtlc: minHtlc,
|
||||
minHtlcIn: minHtlcIn,
|
||||
remoteCsvDelay: csvDelay,
|
||||
updates: updateChan,
|
||||
err: errChan,
|
||||
@ -2381,9 +2383,9 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
||||
}
|
||||
|
||||
// Check that the custom minHTLC value is sent.
|
||||
if openChannelReq.HtlcMinimum != minHtlc {
|
||||
if openChannelReq.HtlcMinimum != minHtlcIn {
|
||||
t.Fatalf("expected OpenChannel to have minHtlc %v, got %v",
|
||||
minHtlc, openChannelReq.HtlcMinimum)
|
||||
minHtlcIn, openChannelReq.HtlcMinimum)
|
||||
}
|
||||
|
||||
chanID := openChannelReq.PendingChannelID
|
||||
@ -2468,7 +2470,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
||||
|
||||
// The minimum HTLC value Alice can offer should be 5, and the minimum
|
||||
// Bob can offer should be 1234.
|
||||
if err := assertMinHtlc(resCtx, 5, minHtlc); err != nil {
|
||||
if err := assertMinHtlc(resCtx, 5, minHtlcIn); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -2482,7 +2484,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := assertMinHtlc(resCtx, minHtlc, 5); err != nil {
|
||||
if err := assertMinHtlc(resCtx, minHtlcIn, 5); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -2543,7 +2545,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
|
||||
// announcements. Alice should advertise the default MinHTLC value of
|
||||
// 5, while bob should advertise the value minHtlc, since Alice
|
||||
// required him to use it.
|
||||
assertChannelAnnouncements(t, alice, bob, capacity, 5, minHtlc)
|
||||
assertChannelAnnouncements(t, alice, bob, capacity, 5, minHtlcIn)
|
||||
|
||||
// The funding transaction is now confirmed, wait for the
|
||||
// OpenStatusUpdate_ChanOpen update
|
||||
|
@ -71,10 +71,8 @@ const (
|
||||
// the error possibly carrying along a ChannelUpdate message that includes the
|
||||
// latest policy.
|
||||
type ForwardingPolicy struct {
|
||||
// MinHTLC is the smallest HTLC that is to be forwarded. This is
|
||||
// set when a channel is first opened, and will be static for the
|
||||
// lifetime of the channel.
|
||||
MinHTLC lnwire.MilliSatoshi
|
||||
// MinHTLC 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
|
||||
@ -2218,9 +2216,9 @@ func (l *channelLink) canSendHtlc(policy ForwardingPolicy,
|
||||
// As our first sanity check, we'll ensure that the passed HTLC isn't
|
||||
// too small for the next hop. If so, then we'll cancel the HTLC
|
||||
// directly.
|
||||
if amt < policy.MinHTLC {
|
||||
if amt < policy.MinHTLCOut {
|
||||
l.log.Errorf("outgoing htlc(%x) is too small: min_htlc=%v, "+
|
||||
"htlc_value=%v", payHash[:], policy.MinHTLC,
|
||||
"htlc_value=%v", payHash[:], policy.MinHTLCOut,
|
||||
amt)
|
||||
|
||||
// As part of the returned error, we'll send our latest routing
|
||||
|
@ -1694,7 +1694,7 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) (
|
||||
quit: make(chan struct{}),
|
||||
}
|
||||
globalPolicy = ForwardingPolicy{
|
||||
MinHTLC: lnwire.NewMSatFromSatoshis(5),
|
||||
MinHTLCOut: lnwire.NewMSatFromSatoshis(5),
|
||||
MaxHTLC: lnwire.NewMSatFromSatoshis(chanAmt),
|
||||
BaseFee: lnwire.NewMSatFromSatoshis(1),
|
||||
TimeLockDelta: 6,
|
||||
@ -4253,7 +4253,7 @@ func (h *persistentLinkHarness) restartLink(
|
||||
}
|
||||
|
||||
globalPolicy = ForwardingPolicy{
|
||||
MinHTLC: lnwire.NewMSatFromSatoshis(5),
|
||||
MinHTLCOut: lnwire.NewMSatFromSatoshis(5),
|
||||
BaseFee: lnwire.NewMSatFromSatoshis(1),
|
||||
TimeLockDelta: 6,
|
||||
}
|
||||
@ -5512,7 +5512,7 @@ func TestCheckHtlcForward(t *testing.T) {
|
||||
cfg: ChannelLinkConfig{
|
||||
FwrdingPolicy: ForwardingPolicy{
|
||||
TimeLockDelta: 20,
|
||||
MinHTLC: 500,
|
||||
MinHTLCOut: 500,
|
||||
MaxHTLC: 1000,
|
||||
BaseFee: 10,
|
||||
},
|
||||
|
@ -1078,7 +1078,7 @@ func newHopNetwork() *hopNetwork {
|
||||
defaultDelta := uint32(6)
|
||||
|
||||
globalPolicy := ForwardingPolicy{
|
||||
MinHTLC: lnwire.NewMSatFromSatoshis(5),
|
||||
MinHTLCOut: lnwire.NewMSatFromSatoshis(5),
|
||||
BaseFee: lnwire.NewMSatFromSatoshis(1),
|
||||
TimeLockDelta: defaultDelta,
|
||||
}
|
||||
|
2
lnd.go
2
lnd.go
@ -479,7 +479,7 @@ func Main(lisCfg ListenerCfg) error {
|
||||
// Set up an autopilot manager from the current config. This will be
|
||||
// used to manage the underlying autopilot agent, starting and stopping
|
||||
// it at will.
|
||||
atplCfg, err := initAutoPilot(server, cfg.Autopilot)
|
||||
atplCfg, err := initAutoPilot(server, cfg.Autopilot, mainChain)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Unable to initialize autopilot: %v", err)
|
||||
ltndLog.Error(err)
|
||||
|
1150
lnrpc/rpc.pb.go
1150
lnrpc/rpc.pb.go
File diff suppressed because it is too large
Load Diff
@ -2686,6 +2686,12 @@ message PolicyUpdateRequest {
|
||||
|
||||
/// If set, the maximum HTLC size in milli-satoshis. If unset, the maximum HTLC will be unchanged.
|
||||
uint64 max_htlc_msat = 6 [json_name = "max_htlc_msat"];
|
||||
|
||||
/// The minimum HTLC size in milli-satoshis. Only applied if min_htlc_msat_specified is true.
|
||||
uint64 min_htlc_msat = 7 [json_name = "min_htlc_msat"];
|
||||
|
||||
/// If true, min_htlc_msat is applied.
|
||||
bool min_htlc_msat_specified = 8 [json_name = "set_min_htlc_msat"];
|
||||
}
|
||||
message PolicyUpdateResponse {
|
||||
}
|
||||
|
@ -3538,6 +3538,16 @@
|
||||
"type": "string",
|
||||
"format": "uint64",
|
||||
"description": "/ If set, the maximum HTLC size in milli-satoshis. If unset, the maximum HTLC will be unchanged."
|
||||
},
|
||||
"min_htlc_msat": {
|
||||
"type": "string",
|
||||
"format": "uint64",
|
||||
"description": "/ The minimum HTLC size in milli-satoshis. Only applied if min_htlc_msat_specified is true."
|
||||
},
|
||||
"min_htlc_msat_specified": {
|
||||
"type": "boolean",
|
||||
"format": "boolean",
|
||||
"description": "/ If true, min_htlc_msat is applied."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
4
log.go
4
log.go
@ -31,6 +31,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/netann"
|
||||
"github.com/lightningnetwork/lnd/peernotifier"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
"github.com/lightningnetwork/lnd/routing/localchans"
|
||||
"github.com/lightningnetwork/lnd/signal"
|
||||
"github.com/lightningnetwork/lnd/sweep"
|
||||
"github.com/lightningnetwork/lnd/watchtower"
|
||||
@ -79,7 +80,6 @@ func init() {
|
||||
addSubLogger("CHDB", channeldb.UseLogger)
|
||||
addSubLogger("HSWC", htlcswitch.UseLogger)
|
||||
addSubLogger("CMGR", connmgr.UseLogger)
|
||||
addSubLogger("CRTR", routing.UseLogger)
|
||||
addSubLogger("BTCN", neutrino.UseLogger)
|
||||
addSubLogger("CNCT", contractcourt.UseLogger)
|
||||
addSubLogger("SPHX", sphinx.UseLogger)
|
||||
@ -99,6 +99,8 @@ func init() {
|
||||
addSubLogger("PRNF", peernotifier.UseLogger)
|
||||
addSubLogger("CHFD", chanfunding.UseLogger)
|
||||
|
||||
addSubLogger(routing.Subsystem, routing.UseLogger)
|
||||
addSubLogger(routing.Subsystem, localchans.UseLogger)
|
||||
addSubLogger(routerrpc.Subsystem, routerrpc.UseLogger)
|
||||
addSubLogger(wtclientrpc.Subsystem, wtclientrpc.UseLogger)
|
||||
addSubLogger(chanfitness.Subsystem, chanfitness.UseLogger)
|
||||
|
4
peer.go
4
peer.go
@ -531,7 +531,7 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) (
|
||||
var forwardingPolicy *htlcswitch.ForwardingPolicy
|
||||
if selfPolicy != nil {
|
||||
forwardingPolicy = &htlcswitch.ForwardingPolicy{
|
||||
MinHTLC: selfPolicy.MinHTLC,
|
||||
MinHTLCOut: selfPolicy.MinHTLC,
|
||||
MaxHTLC: selfPolicy.MaxHTLC,
|
||||
BaseFee: selfPolicy.FeeBaseMSat,
|
||||
FeeRate: selfPolicy.FeeProportionalMillionths,
|
||||
@ -1862,7 +1862,7 @@ out:
|
||||
fwdMinHtlc := lnChan.FwdMinHtlc()
|
||||
defaultPolicy := p.server.cc.routingPolicy
|
||||
forwardingPolicy := &htlcswitch.ForwardingPolicy{
|
||||
MinHTLC: fwdMinHtlc,
|
||||
MinHTLCOut: fwdMinHtlc,
|
||||
MaxHTLC: newChan.LocalChanCfg.MaxPendingAmount,
|
||||
BaseFee: defaultPolicy.BaseFee,
|
||||
FeeRate: defaultPolicy.FeeRate,
|
||||
|
33
pilot.go
33
pilot.go
@ -70,10 +70,11 @@ func validateAtplCfg(cfg *autoPilotConfig) ([]*autopilot.WeightedHeuristic,
|
||||
// chanController is an implementation of the autopilot.ChannelController
|
||||
// interface that's backed by a running lnd instance.
|
||||
type chanController struct {
|
||||
server *server
|
||||
private bool
|
||||
minConfs int32
|
||||
confTarget uint32
|
||||
server *server
|
||||
private bool
|
||||
minConfs int32
|
||||
confTarget uint32
|
||||
chanMinHtlcIn lnwire.MilliSatoshi
|
||||
}
|
||||
|
||||
// OpenChannel opens a channel to a target peer, with a capacity of the
|
||||
@ -91,9 +92,6 @@ func (c *chanController) OpenChannel(target *btcec.PublicKey,
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(halseth): make configurable?
|
||||
minHtlc := lnwire.NewMSatFromSatoshis(1)
|
||||
|
||||
// Construct the open channel request and send it to the server to begin
|
||||
// the funding workflow.
|
||||
req := &openChanReq{
|
||||
@ -102,7 +100,7 @@ func (c *chanController) OpenChannel(target *btcec.PublicKey,
|
||||
subtractFees: true,
|
||||
localFundingAmt: amt,
|
||||
pushAmt: 0,
|
||||
minHtlc: minHtlc,
|
||||
minHtlcIn: c.chanMinHtlcIn,
|
||||
fundingFeePerKw: feePerKw,
|
||||
private: c.private,
|
||||
remoteCsvDelay: 0,
|
||||
@ -136,11 +134,13 @@ func (c *chanController) SpliceOut(chanPoint *wire.OutPoint,
|
||||
// autopilot.ChannelController interface.
|
||||
var _ autopilot.ChannelController = (*chanController)(nil)
|
||||
|
||||
// initAutoPilot initializes a new autopilot.ManagerCfg to manage an
|
||||
// autopilot.Agent instance based on the passed configuration struct. The agent
|
||||
// and all interfaces needed to drive it won't be launched before the Manager's
|
||||
// initAutoPilot initializes a new autopilot.ManagerCfg to manage an autopilot.
|
||||
// Agent instance based on the passed configuration structs. The agent and all
|
||||
// interfaces needed to drive it won't be launched before the Manager's
|
||||
// StartAgent method is called.
|
||||
func initAutoPilot(svr *server, cfg *autoPilotConfig) (*autopilot.ManagerCfg, error) {
|
||||
func initAutoPilot(svr *server, cfg *autoPilotConfig, chainCfg *chainConfig) (
|
||||
*autopilot.ManagerCfg, error) {
|
||||
|
||||
atplLog.Infof("Instantiating autopilot with max_channels=%d, allocation=%f, "+
|
||||
"min_chan_size=%d, max_chan_size=%d, private=%t, min_confs=%d, "+
|
||||
"conf_target=%d", cfg.MaxChannels, cfg.Allocation, cfg.MinChannelSize,
|
||||
@ -173,10 +173,11 @@ func initAutoPilot(svr *server, cfg *autoPilotConfig) (*autopilot.ManagerCfg, er
|
||||
Self: self,
|
||||
Heuristic: weightedAttachment,
|
||||
ChanController: &chanController{
|
||||
server: svr,
|
||||
private: cfg.Private,
|
||||
minConfs: cfg.MinConfs,
|
||||
confTarget: cfg.ConfTarget,
|
||||
server: svr,
|
||||
private: cfg.Private,
|
||||
minConfs: cfg.MinConfs,
|
||||
confTarget: cfg.ConfTarget,
|
||||
chanMinHtlcIn: chainCfg.MinHTLCIn,
|
||||
},
|
||||
WalletBalance: func() (btcutil.Amount, error) {
|
||||
return svr.cc.wallet.ConfirmedBalance(cfg.MinConfs)
|
||||
|
16
routing/localchans/log.go
Normal file
16
routing/localchans/log.go
Normal file
@ -0,0 +1,16 @@
|
||||
package localchans
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
)
|
||||
|
||||
// log is a logger that is initialized with no output filters. This
|
||||
// means the package will not perform any logging by default until the caller
|
||||
// requests it.
|
||||
var log btclog.Logger
|
||||
|
||||
// UseLogger uses a specified Logger to output package logging info. This
|
||||
// function is called from the parent package htlcswitch logger initialization.
|
||||
func UseLogger(logger btclog.Logger) {
|
||||
log = logger
|
||||
}
|
@ -79,6 +79,9 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy,
|
||||
// Apply the new policy to the edge.
|
||||
err := r.updateEdge(info.ChannelPoint, edge, newSchema)
|
||||
if err != nil {
|
||||
log.Warnf("Cannot update policy for %v: %v\n",
|
||||
info.ChannelPoint, err,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -93,7 +96,7 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy,
|
||||
BaseFee: edge.FeeBaseMSat,
|
||||
FeeRate: edge.FeeProportionalMillionths,
|
||||
TimeLockDelta: uint32(edge.TimeLockDelta),
|
||||
MinHTLC: edge.MinHTLC,
|
||||
MinHTLCOut: edge.MinHTLC,
|
||||
MaxHTLC: edge.MaxHTLC,
|
||||
}
|
||||
|
||||
@ -157,6 +160,11 @@ func (r *Manager) updateEdge(chanPoint wire.OutPoint,
|
||||
edge.MaxHTLC = amtMax
|
||||
}
|
||||
|
||||
// If a new min htlc is specified, update the edge.
|
||||
if newSchema.MinHTLC != nil {
|
||||
edge.MinHTLC = *newSchema.MinHTLC
|
||||
}
|
||||
|
||||
// If the MaxHtlc flag wasn't already set, we can set it now.
|
||||
edge.MessageFlags |= lnwire.ChanUpdateOptionMaxHtlc
|
||||
|
||||
|
@ -11,9 +11,11 @@ import (
|
||||
// it.
|
||||
var log btclog.Logger
|
||||
|
||||
const Subsystem = "CRTR"
|
||||
|
||||
// The default amount of logging is none.
|
||||
func init() {
|
||||
UseLogger(build.NewSubLogger("CRTR", nil))
|
||||
UseLogger(build.NewSubLogger(Subsystem, nil))
|
||||
}
|
||||
|
||||
// DisableLog disables all library log output. Logging output is disabled by
|
||||
|
@ -224,6 +224,10 @@ type ChannelPolicy struct {
|
||||
// MaxHTLC is the maximum HTLC size including fees we are allowed to
|
||||
// forward over this channel.
|
||||
MaxHTLC lnwire.MilliSatoshi
|
||||
|
||||
// MinHTLC is the minimum HTLC size including fees we are allowed to
|
||||
// forward over this channel.
|
||||
MinHTLC *lnwire.MilliSatoshi
|
||||
}
|
||||
|
||||
// Config defines the configuration for the ChannelRouter. ALL elements within
|
||||
|
22
rpcserver.go
22
rpcserver.go
@ -1449,7 +1449,7 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
|
||||
|
||||
localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
|
||||
remoteInitialBalance := btcutil.Amount(in.PushSat)
|
||||
minHtlc := lnwire.MilliSatoshi(in.MinHtlcMsat)
|
||||
minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat)
|
||||
remoteCsvDelay := uint16(in.RemoteCsvDelay)
|
||||
|
||||
// Ensure that the initial balance of the remote party (if pushing
|
||||
@ -1537,7 +1537,7 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
|
||||
chainHash: *activeNetParams.GenesisHash,
|
||||
localFundingAmt: localFundingAmt,
|
||||
pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance),
|
||||
minHtlc: minHtlc,
|
||||
minHtlcIn: minHtlcIn,
|
||||
fundingFeePerKw: feeRate,
|
||||
private: in.Private,
|
||||
remoteCsvDelay: remoteCsvDelay,
|
||||
@ -1631,7 +1631,7 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
|
||||
|
||||
localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
|
||||
remoteInitialBalance := btcutil.Amount(in.PushSat)
|
||||
minHtlc := lnwire.MilliSatoshi(in.MinHtlcMsat)
|
||||
minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat)
|
||||
remoteCsvDelay := uint16(in.RemoteCsvDelay)
|
||||
|
||||
// Ensure that the initial balance of the remote party (if pushing
|
||||
@ -1679,7 +1679,7 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
|
||||
chainHash: *activeNetParams.GenesisHash,
|
||||
localFundingAmt: localFundingAmt,
|
||||
pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance),
|
||||
minHtlc: minHtlc,
|
||||
minHtlcIn: minHtlcIn,
|
||||
fundingFeePerKw: feeRate,
|
||||
private: in.Private,
|
||||
remoteCsvDelay: remoteCsvDelay,
|
||||
@ -4864,15 +4864,25 @@ func (r *rpcServer) UpdateChannelPolicy(ctx context.Context,
|
||||
FeeRate: feeRateFixed,
|
||||
}
|
||||
|
||||
maxHtlc := lnwire.MilliSatoshi(req.MaxHtlcMsat)
|
||||
var minHtlc *lnwire.MilliSatoshi
|
||||
if req.MinHtlcMsatSpecified {
|
||||
min := lnwire.MilliSatoshi(req.MinHtlcMsat)
|
||||
minHtlc = &min
|
||||
}
|
||||
|
||||
chanPolicy := routing.ChannelPolicy{
|
||||
FeeSchema: feeSchema,
|
||||
TimeLockDelta: req.TimeLockDelta,
|
||||
MaxHTLC: lnwire.MilliSatoshi(req.MaxHtlcMsat),
|
||||
MaxHTLC: maxHtlc,
|
||||
MinHTLC: minHtlc,
|
||||
}
|
||||
|
||||
rpcsLog.Debugf("[updatechanpolicy] updating channel policy base_fee=%v, "+
|
||||
"rate_float=%v, rate_fixed=%v, time_lock_delta: %v, targets=%v",
|
||||
"rate_float=%v, rate_fixed=%v, time_lock_delta: %v, "+
|
||||
"min_htlc=%v, max_htlc=%v, targets=%v",
|
||||
req.BaseFeeMsat, req.FeeRate, feeRateFixed, req.TimeLockDelta,
|
||||
minHtlc, maxHtlc,
|
||||
spew.Sdump(targetChans))
|
||||
|
||||
// With the scope resolved, we'll now send this to the local channel
|
||||
|
@ -985,6 +985,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
|
||||
return nil, fmt.Errorf("unable to find channel")
|
||||
},
|
||||
DefaultRoutingPolicy: cc.routingPolicy,
|
||||
DefaultMinHtlcIn: cc.minHtlcIn,
|
||||
NumRequiredConfs: func(chanAmt btcutil.Amount,
|
||||
pushAmt lnwire.MilliSatoshi) uint16 {
|
||||
// For large channels we increase the number
|
||||
@ -3084,7 +3085,8 @@ type openChanReq struct {
|
||||
|
||||
private bool
|
||||
|
||||
minHtlc lnwire.MilliSatoshi
|
||||
// minHtlcIn is the minimum incoming htlc that we accept.
|
||||
minHtlcIn lnwire.MilliSatoshi
|
||||
|
||||
remoteCsvDelay uint16
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user