Merge pull request #3697 from joostjager/lower-min-htlc

config: improve management of htlc amount lower limit
This commit is contained in:
Olaoluwa Osuntokun 2019-12-10 18:05:49 -08:00 committed by GitHub
commit 70c5fe3d00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 764 additions and 653 deletions

View File

@ -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,
)

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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,
},

View File

@ -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
View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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 {
}

View File

@ -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
View File

@ -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)

View File

@ -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,

View File

@ -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
View 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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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