multi: distinguish between htlc in and out constraints

This commit is contained in:
Joost Jager 2019-11-15 10:09:27 +01:00
parent d8fd6fae23
commit ddb98fcc41
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
11 changed files with 48 additions and 39 deletions

@ -130,6 +130,8 @@ type chainControl struct {
wallet *lnwallet.LightningWallet wallet *lnwallet.LightningWallet
routingPolicy htlcswitch.ForwardingPolicy routingPolicy htlcswitch.ForwardingPolicy
minHtlcIn lnwire.MilliSatoshi
} }
// newChainControlFromConfig attempts to create a chainControl instance // newChainControlFromConfig attempts to create a chainControl instance
@ -157,21 +159,23 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
switch registeredChains.PrimaryChain() { switch registeredChains.PrimaryChain() {
case bitcoinChain: case bitcoinChain:
cc.routingPolicy = htlcswitch.ForwardingPolicy{ cc.routingPolicy = htlcswitch.ForwardingPolicy{
MinHTLC: cfg.Bitcoin.MinHTLC, MinHTLCOut: cfg.Bitcoin.MinHTLC,
BaseFee: cfg.Bitcoin.BaseFee, BaseFee: cfg.Bitcoin.BaseFee,
FeeRate: cfg.Bitcoin.FeeRate, FeeRate: cfg.Bitcoin.FeeRate,
TimeLockDelta: cfg.Bitcoin.TimeLockDelta, TimeLockDelta: cfg.Bitcoin.TimeLockDelta,
} }
cc.minHtlcIn = cfg.Bitcoin.MinHTLC
cc.feeEstimator = chainfee.NewStaticEstimator( cc.feeEstimator = chainfee.NewStaticEstimator(
defaultBitcoinStaticFeePerKW, 0, defaultBitcoinStaticFeePerKW, 0,
) )
case litecoinChain: case litecoinChain:
cc.routingPolicy = htlcswitch.ForwardingPolicy{ cc.routingPolicy = htlcswitch.ForwardingPolicy{
MinHTLC: cfg.Litecoin.MinHTLC, MinHTLCOut: cfg.Litecoin.MinHTLC,
BaseFee: cfg.Litecoin.BaseFee, BaseFee: cfg.Litecoin.BaseFee,
FeeRate: cfg.Litecoin.FeeRate, FeeRate: cfg.Litecoin.FeeRate,
TimeLockDelta: cfg.Litecoin.TimeLockDelta, TimeLockDelta: cfg.Litecoin.TimeLockDelta,
} }
cc.minHtlcIn = cfg.Litecoin.MinHTLC
cc.feeEstimator = chainfee.NewStaticEstimator( cc.feeEstimator = chainfee.NewStaticEstimator(
defaultLitecoinStaticFeePerKW, 0, defaultLitecoinStaticFeePerKW, 0,
) )

@ -285,6 +285,10 @@ type fundingConfig struct {
// initially announcing channels. // initially announcing channels.
DefaultRoutingPolicy htlcswitch.ForwardingPolicy 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 // NumRequiredConfs is a function closure that helps the funding
// manager decide how many confirmations it should require for a // manager decide how many confirmations it should require for a
// channel extended to it. The function is able to take into account // 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) chanReserve := f.cfg.RequiredRemoteChanReserve(amt, msg.DustLimit)
maxValue := f.cfg.RequiredRemoteMaxValue(amt) maxValue := f.cfg.RequiredRemoteMaxValue(amt)
maxHtlcs := f.cfg.RequiredRemoteMaxHTLCs(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 // Once the reservation has been created successfully, we add it to
// this peer's map of pending reservations to track this particular // this peer's map of pending reservations to track this particular
@ -2806,7 +2810,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
var ( var (
peerKey = msg.peer.IdentityKey() peerKey = msg.peer.IdentityKey()
localAmt = msg.localFundingAmt localAmt = msg.localFundingAmt
minHtlc = msg.minHtlc minHtlcIn = msg.minHtlcIn
remoteCsvDelay = msg.remoteCsvDelay remoteCsvDelay = msg.remoteCsvDelay
) )
@ -2922,8 +2926,8 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
} }
// If no minimum HTLC value was specified, use the default one. // If no minimum HTLC value was specified, use the default one.
if minHtlc == 0 { if minHtlcIn == 0 {
minHtlc = f.cfg.DefaultRoutingPolicy.MinHTLC minHtlcIn = f.cfg.DefaultMinHtlcIn
} }
// If a pending channel map for this peer isn't already created, then // If a pending channel map for this peer isn't already created, then
@ -2938,7 +2942,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
resCtx := &reservationWithCtx{ resCtx := &reservationWithCtx{
chanAmt: capacity, chanAmt: capacity,
remoteCsvDelay: remoteCsvDelay, remoteCsvDelay: remoteCsvDelay,
remoteMinHtlc: minHtlc, remoteMinHtlc: minHtlcIn,
reservation: reservation, reservation: reservation,
peer: msg.peer, peer: msg.peer,
updates: msg.updates, updates: msg.updates,
@ -2972,7 +2976,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
DustLimit: ourContribution.DustLimit, DustLimit: ourContribution.DustLimit,
MaxValueInFlight: maxValue, MaxValueInFlight: maxValue,
ChannelReserve: chanReserve, ChannelReserve: chanReserve,
HtlcMinimum: minHtlc, HtlcMinimum: minHtlcIn,
FeePerKiloWeight: uint32(commitFeePerKw), FeePerKiloWeight: uint32(commitFeePerKw),
CsvDelay: remoteCsvDelay, CsvDelay: remoteCsvDelay,
MaxAcceptedHTLCs: maxHtlcs, MaxAcceptedHTLCs: maxHtlcs,

@ -336,11 +336,12 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
return nil, fmt.Errorf("unable to find channel") return nil, fmt.Errorf("unable to find channel")
}, },
DefaultRoutingPolicy: htlcswitch.ForwardingPolicy{ DefaultRoutingPolicy: htlcswitch.ForwardingPolicy{
MinHTLC: 5, MinHTLCOut: 5,
BaseFee: 100, BaseFee: 100,
FeeRate: 1000, FeeRate: 1000,
TimeLockDelta: 10, TimeLockDelta: 10,
}, },
DefaultMinHtlcIn: 5,
NumRequiredConfs: func(chanAmt btcutil.Amount, NumRequiredConfs: func(chanAmt btcutil.Amount,
pushAmt lnwire.MilliSatoshi) uint16 { pushAmt lnwire.MilliSatoshi) uint16 {
return 3 return 3
@ -464,11 +465,12 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) {
TempChanIDSeed: oldCfg.TempChanIDSeed, TempChanIDSeed: oldCfg.TempChanIDSeed,
FindChannel: oldCfg.FindChannel, FindChannel: oldCfg.FindChannel,
DefaultRoutingPolicy: htlcswitch.ForwardingPolicy{ DefaultRoutingPolicy: htlcswitch.ForwardingPolicy{
MinHTLC: 5, MinHTLCOut: 5,
BaseFee: 100, BaseFee: 100,
FeeRate: 1000, FeeRate: 1000,
TimeLockDelta: 10, TimeLockDelta: 10,
}, },
DefaultMinHtlcIn: 5,
RequiredRemoteMaxValue: oldCfg.RequiredRemoteMaxValue, RequiredRemoteMaxValue: oldCfg.RequiredRemoteMaxValue,
PublishTransaction: func(txn *wire.MsgTx) error { PublishTransaction: func(txn *wire.MsgTx) error {
publishChan <- txn publishChan <- txn
@ -926,7 +928,7 @@ func assertChannelAnnouncements(t *testing.T, alice, bob *testNode,
// _other_ node. // _other_ node.
other := (j + 1) % 2 other := (j + 1) % 2
minHtlc := nodes[other].fundingMgr.cfg. minHtlc := nodes[other].fundingMgr.cfg.
DefaultRoutingPolicy.MinHTLC DefaultMinHtlcIn
// We might expect a custom MinHTLC value. // We might expect a custom MinHTLC value.
if len(customMinHtlc) > 0 { if len(customMinHtlc) > 0 {
@ -2325,7 +2327,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
// This is the custom parameters we'll use. // This is the custom parameters we'll use.
const csvDelay = 67 const csvDelay = 67
const minHtlc = 1234 const minHtlcIn = 1234
// 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.
@ -2344,7 +2346,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
localFundingAmt: localAmt, localFundingAmt: localAmt,
pushAmt: lnwire.NewMSatFromSatoshis(pushAmt), pushAmt: lnwire.NewMSatFromSatoshis(pushAmt),
private: false, private: false,
minHtlc: minHtlc, minHtlcIn: minHtlcIn,
remoteCsvDelay: csvDelay, remoteCsvDelay: csvDelay,
updates: updateChan, updates: updateChan,
err: errChan, err: errChan,
@ -2381,9 +2383,9 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
} }
// Check that the custom minHTLC value is sent. // 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", t.Fatalf("expected OpenChannel to have minHtlc %v, got %v",
minHtlc, openChannelReq.HtlcMinimum) minHtlcIn, openChannelReq.HtlcMinimum)
} }
chanID := openChannelReq.PendingChannelID 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 // The minimum HTLC value Alice can offer should be 5, and the minimum
// Bob can offer should be 1234. // 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) t.Fatal(err)
} }
@ -2482,7 +2484,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if err := assertMinHtlc(resCtx, minHtlc, 5); err != nil { if err := assertMinHtlc(resCtx, minHtlcIn, 5); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -2543,7 +2545,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
// announcements. Alice should advertise the default MinHTLC value of // announcements. Alice should advertise the default MinHTLC value of
// 5, while bob should advertise the value minHtlc, since Alice // 5, while bob should advertise the value minHtlc, since Alice
// required him to use it. // 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 // The funding transaction is now confirmed, wait for the
// OpenStatusUpdate_ChanOpen update // OpenStatusUpdate_ChanOpen update

@ -71,10 +71,8 @@ const (
// the error possibly carrying along a ChannelUpdate message that includes the // the error possibly carrying along a ChannelUpdate message that includes the
// latest policy. // latest policy.
type ForwardingPolicy struct { type ForwardingPolicy struct {
// MinHTLC is the smallest HTLC that is to be forwarded. This is // MinHTLC is the smallest HTLC that is to be forwarded.
// set when a channel is first opened, and will be static for the MinHTLCOut lnwire.MilliSatoshi
// lifetime of the channel.
MinHTLC lnwire.MilliSatoshi
// MaxHTLC is the largest HTLC that is to be forwarded. // MaxHTLC is the largest HTLC that is to be forwarded.
MaxHTLC lnwire.MilliSatoshi 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 // 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 // too small for the next hop. If so, then we'll cancel the HTLC
// directly. // directly.
if amt < policy.MinHTLC { if amt < policy.MinHTLCOut {
l.log.Errorf("outgoing htlc(%x) is too small: min_htlc=%v, "+ 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) amt)
// As part of the returned error, we'll send our latest routing // 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{}), quit: make(chan struct{}),
} }
globalPolicy = ForwardingPolicy{ globalPolicy = ForwardingPolicy{
MinHTLC: lnwire.NewMSatFromSatoshis(5), MinHTLCOut: lnwire.NewMSatFromSatoshis(5),
MaxHTLC: lnwire.NewMSatFromSatoshis(chanAmt), MaxHTLC: lnwire.NewMSatFromSatoshis(chanAmt),
BaseFee: lnwire.NewMSatFromSatoshis(1), BaseFee: lnwire.NewMSatFromSatoshis(1),
TimeLockDelta: 6, TimeLockDelta: 6,
@ -4253,7 +4253,7 @@ func (h *persistentLinkHarness) restartLink(
} }
globalPolicy = ForwardingPolicy{ globalPolicy = ForwardingPolicy{
MinHTLC: lnwire.NewMSatFromSatoshis(5), MinHTLCOut: lnwire.NewMSatFromSatoshis(5),
BaseFee: lnwire.NewMSatFromSatoshis(1), BaseFee: lnwire.NewMSatFromSatoshis(1),
TimeLockDelta: 6, TimeLockDelta: 6,
} }
@ -5512,7 +5512,7 @@ func TestCheckHtlcForward(t *testing.T) {
cfg: ChannelLinkConfig{ cfg: ChannelLinkConfig{
FwrdingPolicy: ForwardingPolicy{ FwrdingPolicy: ForwardingPolicy{
TimeLockDelta: 20, TimeLockDelta: 20,
MinHTLC: 500, MinHTLCOut: 500,
MaxHTLC: 1000, MaxHTLC: 1000,
BaseFee: 10, BaseFee: 10,
}, },

@ -1078,7 +1078,7 @@ func newHopNetwork() *hopNetwork {
defaultDelta := uint32(6) defaultDelta := uint32(6)
globalPolicy := ForwardingPolicy{ globalPolicy := ForwardingPolicy{
MinHTLC: lnwire.NewMSatFromSatoshis(5), MinHTLCOut: lnwire.NewMSatFromSatoshis(5),
BaseFee: lnwire.NewMSatFromSatoshis(1), BaseFee: lnwire.NewMSatFromSatoshis(1),
TimeLockDelta: defaultDelta, TimeLockDelta: defaultDelta,
} }

@ -531,7 +531,7 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) (
var forwardingPolicy *htlcswitch.ForwardingPolicy var forwardingPolicy *htlcswitch.ForwardingPolicy
if selfPolicy != nil { if selfPolicy != nil {
forwardingPolicy = &htlcswitch.ForwardingPolicy{ forwardingPolicy = &htlcswitch.ForwardingPolicy{
MinHTLC: selfPolicy.MinHTLC, MinHTLCOut: selfPolicy.MinHTLC,
MaxHTLC: selfPolicy.MaxHTLC, MaxHTLC: selfPolicy.MaxHTLC,
BaseFee: selfPolicy.FeeBaseMSat, BaseFee: selfPolicy.FeeBaseMSat,
FeeRate: selfPolicy.FeeProportionalMillionths, FeeRate: selfPolicy.FeeProportionalMillionths,
@ -1862,7 +1862,7 @@ out:
fwdMinHtlc := lnChan.FwdMinHtlc() fwdMinHtlc := lnChan.FwdMinHtlc()
defaultPolicy := p.server.cc.routingPolicy defaultPolicy := p.server.cc.routingPolicy
forwardingPolicy := &htlcswitch.ForwardingPolicy{ forwardingPolicy := &htlcswitch.ForwardingPolicy{
MinHTLC: fwdMinHtlc, MinHTLCOut: fwdMinHtlc,
MaxHTLC: newChan.LocalChanCfg.MaxPendingAmount, MaxHTLC: newChan.LocalChanCfg.MaxPendingAmount,
BaseFee: defaultPolicy.BaseFee, BaseFee: defaultPolicy.BaseFee,
FeeRate: defaultPolicy.FeeRate, FeeRate: defaultPolicy.FeeRate,

@ -92,7 +92,7 @@ func (c *chanController) OpenChannel(target *btcec.PublicKey,
} }
// TODO(halseth): make configurable? // TODO(halseth): make configurable?
minHtlc := lnwire.NewMSatFromSatoshis(1) minHtlcIn := lnwire.NewMSatFromSatoshis(1)
// Construct the open channel request and send it to the server to begin // Construct the open channel request and send it to the server to begin
// the funding workflow. // the funding workflow.
@ -102,7 +102,7 @@ func (c *chanController) OpenChannel(target *btcec.PublicKey,
subtractFees: true, subtractFees: true,
localFundingAmt: amt, localFundingAmt: amt,
pushAmt: 0, pushAmt: 0,
minHtlc: minHtlc, minHtlcIn: minHtlcIn,
fundingFeePerKw: feePerKw, fundingFeePerKw: feePerKw,
private: c.private, private: c.private,
remoteCsvDelay: 0, remoteCsvDelay: 0,

@ -93,7 +93,7 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy,
BaseFee: edge.FeeBaseMSat, BaseFee: edge.FeeBaseMSat,
FeeRate: edge.FeeProportionalMillionths, FeeRate: edge.FeeProportionalMillionths,
TimeLockDelta: uint32(edge.TimeLockDelta), TimeLockDelta: uint32(edge.TimeLockDelta),
MinHTLC: edge.MinHTLC, MinHTLCOut: edge.MinHTLC,
MaxHTLC: edge.MaxHTLC, MaxHTLC: edge.MaxHTLC,
} }

@ -1449,7 +1449,7 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
localFundingAmt := btcutil.Amount(in.LocalFundingAmount) localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
remoteInitialBalance := btcutil.Amount(in.PushSat) remoteInitialBalance := btcutil.Amount(in.PushSat)
minHtlc := lnwire.MilliSatoshi(in.MinHtlcMsat) minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat)
remoteCsvDelay := uint16(in.RemoteCsvDelay) remoteCsvDelay := uint16(in.RemoteCsvDelay)
// Ensure that the initial balance of the remote party (if pushing // 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, chainHash: *activeNetParams.GenesisHash,
localFundingAmt: localFundingAmt, localFundingAmt: localFundingAmt,
pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance), pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance),
minHtlc: minHtlc, minHtlcIn: minHtlcIn,
fundingFeePerKw: feeRate, fundingFeePerKw: feeRate,
private: in.Private, private: in.Private,
remoteCsvDelay: remoteCsvDelay, remoteCsvDelay: remoteCsvDelay,
@ -1631,7 +1631,7 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
localFundingAmt := btcutil.Amount(in.LocalFundingAmount) localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
remoteInitialBalance := btcutil.Amount(in.PushSat) remoteInitialBalance := btcutil.Amount(in.PushSat)
minHtlc := lnwire.MilliSatoshi(in.MinHtlcMsat) minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat)
remoteCsvDelay := uint16(in.RemoteCsvDelay) remoteCsvDelay := uint16(in.RemoteCsvDelay)
// Ensure that the initial balance of the remote party (if pushing // 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, chainHash: *activeNetParams.GenesisHash,
localFundingAmt: localFundingAmt, localFundingAmt: localFundingAmt,
pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance), pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance),
minHtlc: minHtlc, minHtlcIn: minHtlcIn,
fundingFeePerKw: feeRate, fundingFeePerKw: feeRate,
private: in.Private, private: in.Private,
remoteCsvDelay: remoteCsvDelay, remoteCsvDelay: remoteCsvDelay,

@ -985,6 +985,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
return nil, fmt.Errorf("unable to find channel") return nil, fmt.Errorf("unable to find channel")
}, },
DefaultRoutingPolicy: cc.routingPolicy, DefaultRoutingPolicy: cc.routingPolicy,
DefaultMinHtlcIn: cc.minHtlcIn,
NumRequiredConfs: func(chanAmt btcutil.Amount, NumRequiredConfs: func(chanAmt btcutil.Amount,
pushAmt lnwire.MilliSatoshi) uint16 { pushAmt lnwire.MilliSatoshi) uint16 {
// For large channels we increase the number // For large channels we increase the number
@ -3084,8 +3085,8 @@ type openChanReq struct {
private bool private bool
// minHtlc is the minimum incoming htlc that we accept. // minHtlcIn is the minimum incoming htlc that we accept.
minHtlc lnwire.MilliSatoshi minHtlcIn lnwire.MilliSatoshi
remoteCsvDelay uint16 remoteCsvDelay uint16