diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index 3092385058..4f41fb0220 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -197,6 +197,10 @@ type PartialChainControl struct { // RoutingPolicy is the routing policy we have decided to use. RoutingPolicy models.ForwardingPolicy + // RoutingPolicy is the routing policy we have decided to use for + // private channels. + PrivateRoutingPolicy models.ForwardingPolicy + // MinHtlcIn is the minimum HTLC we will accept. MinHtlcIn lnwire.MilliSatoshi @@ -276,6 +280,12 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) { FeeRate: cfg.Bitcoin.FeeRate, TimeLockDelta: cfg.Bitcoin.TimeLockDelta, } + cc.PrivateRoutingPolicy = models.ForwardingPolicy{ + MinHTLCOut: cfg.Bitcoin.MinHTLCOut, + BaseFee: cfg.Bitcoin.PrivateBaseFee, + FeeRate: cfg.Bitcoin.PrivateFeeRate, + TimeLockDelta: cfg.Bitcoin.PrivateTimeLockDelta, + } cc.MinHtlcIn = cfg.Bitcoin.MinHTLCIn cc.FeeEstimator = chainfee.NewStaticEstimator( DefaultBitcoinStaticFeePerKW, @@ -288,6 +298,12 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) { FeeRate: cfg.Litecoin.FeeRate, TimeLockDelta: cfg.Litecoin.TimeLockDelta, } + cc.PrivateRoutingPolicy = models.ForwardingPolicy{ + MinHTLCOut: cfg.Bitcoin.MinHTLCOut, + BaseFee: cfg.Bitcoin.PrivateBaseFee, + FeeRate: cfg.Bitcoin.PrivateFeeRate, + TimeLockDelta: cfg.Bitcoin.PrivateTimeLockDelta, + } cc.MinHtlcIn = cfg.Litecoin.MinHTLCIn cc.FeeEstimator = chainfee.NewStaticEstimator( DefaultLitecoinStaticFeePerKW, 0, diff --git a/config.go b/config.go index ab42976abe..f2b13052d6 100644 --- a/config.go +++ b/config.go @@ -549,13 +549,16 @@ func DefaultConfig() Config { WSPingInterval: lnrpc.DefaultPingInterval, WSPongWait: lnrpc.DefaultPongWait, Bitcoin: &lncfg.Chain{ - MinHTLCIn: chainreg.DefaultBitcoinMinHTLCInMSat, - MinHTLCOut: chainreg.DefaultBitcoinMinHTLCOutMSat, - BaseFee: chainreg.DefaultBitcoinBaseFeeMSat, - FeeRate: chainreg.DefaultBitcoinFeeRate, - TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta, - MaxLocalDelay: defaultMaxLocalCSVDelay, - Node: "btcd", + MinHTLCIn: chainreg.DefaultBitcoinMinHTLCInMSat, + MinHTLCOut: chainreg.DefaultBitcoinMinHTLCOutMSat, + BaseFee: chainreg.DefaultBitcoinBaseFeeMSat, + FeeRate: chainreg.DefaultBitcoinFeeRate, + TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta, + PrivateBaseFee: chainreg.DefaultBitcoinBaseFeeMSat, + PrivateFeeRate: chainreg.DefaultBitcoinFeeRate, + PrivateTimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta, + MaxLocalDelay: defaultMaxLocalCSVDelay, + Node: "btcd", }, BtcdMode: &lncfg.Btcd{ Dir: defaultBtcdDir, @@ -570,13 +573,16 @@ func DefaultConfig() Config { ZMQReadDeadline: defaultZMQReadDeadline, }, Litecoin: &lncfg.Chain{ - MinHTLCIn: chainreg.DefaultLitecoinMinHTLCInMSat, - MinHTLCOut: chainreg.DefaultLitecoinMinHTLCOutMSat, - BaseFee: chainreg.DefaultLitecoinBaseFeeMSat, - FeeRate: chainreg.DefaultLitecoinFeeRate, - TimeLockDelta: chainreg.DefaultLitecoinTimeLockDelta, - MaxLocalDelay: defaultMaxLocalCSVDelay, - Node: "ltcd", + MinHTLCIn: chainreg.DefaultLitecoinMinHTLCInMSat, + MinHTLCOut: chainreg.DefaultLitecoinMinHTLCOutMSat, + BaseFee: chainreg.DefaultLitecoinBaseFeeMSat, + FeeRate: chainreg.DefaultLitecoinFeeRate, + TimeLockDelta: chainreg.DefaultLitecoinTimeLockDelta, + PrivateBaseFee: chainreg.DefaultBitcoinBaseFeeMSat, + PrivateFeeRate: chainreg.DefaultBitcoinFeeRate, + PrivateTimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta, + MaxLocalDelay: defaultMaxLocalCSVDelay, + Node: "ltcd", }, LtcdMode: &lncfg.Btcd{ Dir: defaultLtcdDir, diff --git a/funding/manager.go b/funding/manager.go index 1f96d13e14..ff15ceee87 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -435,6 +435,10 @@ type Config struct { // initially announcing channels. DefaultRoutingPolicy models.ForwardingPolicy + // DefaultRoutingPolicy is the default routing policy used when + // initially announcing channels. + DefaultPrivateRoutingPolicy models.ForwardingPolicy + // DefaultMinHtlcIn is the default minimum incoming htlc value that is // set as a channel parameter. DefaultMinHtlcIn lnwire.MilliSatoshi @@ -1714,6 +1718,7 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer, ourContribution := reservation.OurContribution() forwardingPolicy := f.defaultForwardingPolicy( ourContribution.ChannelConstraints, + public, ) // Once the reservation has been created successfully, we add it to @@ -3280,10 +3285,17 @@ func (f *Manager) extractAnnounceParams(c *channeldb.OpenChannel) ( // need to determine the smallest HTLC it deems economically relevant. fwdMinHTLC := c.LocalChanCfg.MinHTLC + var policy models.ForwardingPolicy + isPublic := c.ChannelFlags&lnwire.FFAnnounceChannel == 1 + if isPublic { + policy = f.cfg.DefaultRoutingPolicy + } else { + policy = f.cfg.DefaultPrivateRoutingPolicy + } // 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 + if fwdMinHTLC < policy.MinHTLCOut { + fwdMinHTLC = policy.MinHTLCOut } // We'll obtain the max HTLC value we can forward in our direction, as @@ -3314,13 +3326,13 @@ func (f *Manager) addToRouterGraph(completeChan *channeldb.OpenChannel, chanID := lnwire.NewChanIDFromOutPoint(&completeChan.FundingOutpoint) fwdMinHTLC, fwdMaxHTLC := f.extractAnnounceParams(completeChan) - + public := completeChan.ChannelFlags&lnwire.FFAnnounceChannel == 1 ann, err := f.newChanAnnouncement( f.cfg.IDKey, completeChan.IdentityPub, &completeChan.LocalChanCfg.MultiSigKey, completeChan.RemoteChanCfg.MultiSigKey.PubKey, *shortChanID, chanID, fwdMinHTLC, fwdMaxHTLC, ourPolicy, - completeChan.ChanType, + completeChan.ChanType, public, ) if err != nil { return fmt.Errorf("error generating channel "+ @@ -4005,6 +4017,7 @@ func (f *Manager) ensureInitialForwardingPolicy(chanID lnwire.ChannelID, forwardingPolicy = f.defaultForwardingPolicy( channel.LocalChanCfg.ChannelConstraints, + channel.ChannelFlags&lnwire.FFAnnounceChannel == 1, ) needDBUpdate = true } @@ -4056,7 +4069,8 @@ func (f *Manager) newChanAnnouncement(localPubKey, remoteFundingKey *btcec.PublicKey, shortChanID lnwire.ShortChannelID, chanID lnwire.ChannelID, fwdMinHTLC, fwdMaxHTLC lnwire.MilliSatoshi, ourPolicy *channeldb.ChannelEdgePolicy, - chanType channeldb.ChannelType) (*chanAnnouncement, error) { + chanType channeldb.ChannelType, public bool, +) (*chanAnnouncement, error) { chainHash := *f.cfg.Wallet.Cfg.NetParams.GenesisHash @@ -4131,6 +4145,12 @@ func (f *Manager) newChanAnnouncement(localPubKey, // max_htlc field. msgFlags := lnwire.ChanUpdateRequiredMaxHtlc + var defaultpolicy models.ForwardingPolicy + if public { + defaultpolicy = f.cfg.DefaultRoutingPolicy + } else { + defaultpolicy = f.cfg.DefaultPrivateRoutingPolicy + } // We announce the channel with the default values. Some of // these values can later be changed by crafting a new ChannelUpdate. chanUpdateAnn := &lnwire.ChannelUpdate{ @@ -4140,7 +4160,7 @@ func (f *Manager) newChanAnnouncement(localPubKey, MessageFlags: msgFlags, ChannelFlags: chanFlags, TimeLockDelta: uint16( - f.cfg.DefaultRoutingPolicy.TimeLockDelta, + defaultpolicy.TimeLockDelta, ), HtlcMinimumMsat: fwdMinHTLC, HtlcMaximumMsat: fwdMaxHTLC, @@ -4179,10 +4199,10 @@ func (f *Manager) newChanAnnouncement(localPubKey, "announcement of ChannelID(%v). "+ "Assuming default fee parameters.", chanID) chanUpdateAnn.BaseFee = uint32( - f.cfg.DefaultRoutingPolicy.BaseFee, + defaultpolicy.BaseFee, ) chanUpdateAnn.FeeRate = uint32( - f.cfg.DefaultRoutingPolicy.FeeRate, + defaultpolicy.FeeRate, ) } @@ -4273,7 +4293,7 @@ func (f *Manager) announceChannel(localIDKey, remoteIDKey *btcec.PublicKey, // only use the channel announcement message from the returned struct. ann, err := f.newChanAnnouncement(localIDKey, remoteIDKey, localFundingKey, remoteFundingKey, shortChanID, chanID, - 0, 0, nil, chanType, + 0, 0, nil, chanType, true, ) if err != nil { log.Errorf("can't generate channel announcement: %v", err) @@ -4614,6 +4634,7 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { // values hence we assume default fee settings from the config. forwardingPolicy := f.defaultForwardingPolicy( ourContribution.ChannelConstraints, + !msg.Private, ) if baseFee != nil { forwardingPolicy.BaseFee = lnwire.MilliSatoshi(*baseFee) @@ -4958,14 +4979,25 @@ func copyPubKey(pub *btcec.PublicKey) *btcec.PublicKey { // defaultForwardingPolicy returns the default forwarding policy based on the // default routing policy and our local channel constraints. func (f *Manager) defaultForwardingPolicy( - constraints channeldb.ChannelConstraints) *models.ForwardingPolicy { - - return &models.ForwardingPolicy{ - MinHTLCOut: constraints.MinHTLC, - MaxHTLC: constraints.MaxPendingAmount, - BaseFee: f.cfg.DefaultRoutingPolicy.BaseFee, - FeeRate: f.cfg.DefaultRoutingPolicy.FeeRate, - TimeLockDelta: f.cfg.DefaultRoutingPolicy.TimeLockDelta, + constraints channeldb.ChannelConstraints, + public bool) *models.ForwardingPolicy { + + if public { + return &models.ForwardingPolicy{ + MinHTLCOut: constraints.MinHTLC, + MaxHTLC: constraints.MaxPendingAmount, + BaseFee: f.cfg.DefaultRoutingPolicy.BaseFee, + FeeRate: f.cfg.DefaultRoutingPolicy.FeeRate, + TimeLockDelta: f.cfg.DefaultRoutingPolicy.TimeLockDelta, + } + } else { + return &models.ForwardingPolicy{ + MinHTLCOut: constraints.MinHTLC, + MaxHTLC: constraints.MaxPendingAmount, + BaseFee: f.cfg.DefaultPrivateRoutingPolicy.BaseFee, + FeeRate: f.cfg.DefaultPrivateRoutingPolicy.FeeRate, + TimeLockDelta: f.cfg.DefaultPrivateRoutingPolicy.TimeLockDelta, + } } } diff --git a/lncfg/chain.go b/lncfg/chain.go index 2b9c508293..4f54d69c22 100644 --- a/lncfg/chain.go +++ b/lncfg/chain.go @@ -23,16 +23,19 @@ type Chain struct { SigNetChallenge string `long:"signetchallenge" description:"Connect to a custom signet network defined by this challenge instead of using the global default signet test network -- Can be specified multiple times"` SigNetSeedNode []string `long:"signetseednode" description:"Specify a seed node for the signet network instead of using the global default signet network seed nodes"` - 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."` - MaxLocalDelay uint16 `long:"maxlocaldelay" description:"The maximum blocks we will allow our funds to be timelocked before accessing its funds in case of unilateral close. If a peer proposes a value greater than this, we will reject the channel."` - 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"` - DNSSeeds []string `long:"dnsseed" description:"The seed DNS server(s) to use for initial peer discovery. Must be specified as a '[,]' tuple where the SOA address is needed for DNS resolution through Tor but is optional for clearnet users. Multiple tuples can be specified, will overwrite the default seed servers."` - ChanReserveScript string `long:"chanreservescript" description:"A startlark script using chanAmt variable and returning the required remote channel reserve"` + 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."` + MaxLocalDelay uint16 `long:"maxlocaldelay" description:"The maximum blocks we will allow our funds to be timelocked before accessing its funds in case of unilateral close. If a peer proposes a value greater than this, we will reject the channel."` + 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"` + PrivateBaseFee lnwire.MilliSatoshi `long:"privatebasefee" description:"The base fee in millisatoshi we will charge for forwarding payments on our private channels"` + PrivateFeeRate lnwire.MilliSatoshi `long:"privatefeerate" description:"The fee rate used when forwarding payments on our private channels. The total fee charged is basefee + (amount * feerate / 1000000), where amount is the forwarded amount."` + PrivateTimeLockDelta uint32 `long:"privatetimelockdelta" description:"The CLTV delta we will subtract from a forwarded HTLC's timelock value on private channels"` + DNSSeeds []string `long:"dnsseed" description:"The seed DNS server(s) to use for initial peer discovery. Must be specified as a '[,]' tuple where the SOA address is needed for DNS resolution through Tor but is optional for clearnet users. Multiple tuples can be specified, will overwrite the default seed servers."` + ChanReserveScript string `long:"chanreservescript" description:"A startlark script using chanAmt variable and returning the required remote channel reserve"` } // Validate performs validation on our chain config. diff --git a/peer/brontide.go b/peer/brontide.go index 57a6e28613..b7d60a7875 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -237,6 +237,10 @@ type Config struct { // the Brontide. RoutingPolicy models.ForwardingPolicy + // PrivateRoutingPolicy is used to set the forwarding policy for links + // created by the Brontide on private channels. + PrivateRoutingPolicy models.ForwardingPolicy + // Sphinx is used when setting up ChannelLinks so they can decode sphinx // onion blobs. Sphinx *hop.OnionProcessor @@ -898,7 +902,12 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) ( p.log.Warnf("Unable to find our forwarding policy "+ "for channel %v, using default values", chanPoint) - forwardingPolicy = &p.cfg.RoutingPolicy + isPublic := dbChan.ChannelFlags&lnwire.FFAnnounceChannel == 1 + if isPublic { + forwardingPolicy = &p.cfg.RoutingPolicy + } else { + forwardingPolicy = &p.cfg.PrivateRoutingPolicy + } } p.log.Tracef("Using link policy of: %v", diff --git a/server.go b/server.go index 737fed8ae6..99813ac06b 100644 --- a/server.go +++ b/server.go @@ -1320,12 +1320,13 @@ func newServer(cfg *Config, listenAddrs []net.Addr, return s.genNodeAnnouncement(nil) }, - SendAnnouncement: s.authGossiper.ProcessLocalAnnouncement, - NotifyWhenOnline: s.NotifyWhenOnline, - TempChanIDSeed: chanIDSeed, - FindChannel: s.findChannel, - DefaultRoutingPolicy: cc.RoutingPolicy, - DefaultMinHtlcIn: cc.MinHtlcIn, + SendAnnouncement: s.authGossiper.ProcessLocalAnnouncement, + NotifyWhenOnline: s.NotifyWhenOnline, + TempChanIDSeed: chanIDSeed, + FindChannel: s.findChannel, + DefaultRoutingPolicy: cc.RoutingPolicy, + DefaultPrivateRoutingPolicy: cc.PrivateRoutingPolicy, + DefaultMinHtlcIn: cc.MinHtlcIn, NumRequiredConfs: func(chanAmt btcutil.Amount, pushAmt lnwire.MilliSatoshi) uint16 { // For large channels we increase the number @@ -3858,6 +3859,7 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, Wallet: s.cc.Wallet, ChainNotifier: s.cc.ChainNotifier, RoutingPolicy: s.cc.RoutingPolicy, + PrivateRoutingPolicy: s.cc.PrivateRoutingPolicy, Sphinx: s.sphinx, WitnessBeacon: s.witnessBeacon, Invoices: s.invoices,