Skip to content

Commit

Permalink
Simplify outgoing and incoming fields
Browse files Browse the repository at this point in the history
  • Loading branch information
aftermath2 committed May 18, 2024
1 parent 44c88d8 commit da721be
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 130 deletions.
33 changes: 18 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,25 +162,28 @@ Parameters related to the initiator node's channels.
| **max_htlc** | stat_range | Channels maximum HTLC |
| **last_update_diff** | stat_range | Channels last update difference to the time of the request (seconds) |
| **together** | range | Number of channels that the host node and initiator node have together |
| **incoming_fee_rates** | stat_range | Channels incoming fee rates |
| **outgoing_fee_rates** | stat_range | Channels outgoing fee rates |
| **incoming_base_fees** | stat_range | Channels incoming base fees |
| **outgoing_base_fees** | stat_range | Channels outgoing base fees |
| **outgoing_disabled** | stat_range | Number of outgoing disabled channels. The value type is float and should be between 0 and 1 |
| **incoming_disabled** | stat_range | Number of incoming disabled channels. The value type is float and should be between 0 and 1 |
| **incoming_inbound_fee_rates** | stat_range | Channels incoming inbound fee rates |
| **outgoing_inbound_fee_rates** | stat_range | Channels outgoing inbound fee rates |
| **incoming_inbound_base_fees** | stat_range | Channels incoming inbound base fees |
| **outgoing_inbound_base_fees** | stat_range | Channels outgoing inbound base fees |
> [!Note]
> **Outgoing** refers to the channel value from the initiator's node side, **incoming** to the value corresponding to the initiator node's peer side.
>
> For instance, let's say Bob wants to open a channel with us and he already has one with Charlie. Bob has a base fee of 0 sats and Charlie has a base fee of 1 sat. In this case, the outgoing base fee is 0 sats (Bob's side) and the incoming base fee is 1 sat (Charlie's side).
| **fee_rates** | stat_range | Channels fee rates |
| **base_fees** | stat_range | Channels base fees |
| **disabled** | stat_range | Number of disabled channels. The value type is float and should be between 0 and 1 |
| **inbound_fee_rates** | stat_range | Channels inbound fee rates |
| **inbound_base_fees** | stat_range | Channels inbound base fees |
| **peers** | [Peers](#Peers) | Initiator node channels parameters on the peers' side |
> [!Note]
> **Inbound** fees were added in LND v0.18.0-beta and they represent fees for the movement of incoming funds. A positive value would discourage peers from routing to the channel and a negative value would incentivize them.
#### Peers
Initiator node channels parameters on the peers' side.
| Key | Type | Description |
| -- | -- | -- |
| **fee_rates** | stat_range | Channels fee rates |
| **base_fees** | stat_range | Channels base fees |
| **disabled** | stat_range | Number of disabled channels. The value type is float and should be between 0 and 1 |
| **inbound_fee_rates** | stat_range | Channels inbound fee rates |
| **inbound_base_fees** | stat_range | Channels inbound base fees |
#### Range
A range may have a minimum value, a maximum value or both defined. All values are in **satoshis**.
Expand Down
4 changes: 2 additions & 2 deletions examples/advanced.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ policies:
age:
min: 52_560
channels:
outgoing_fee_rates:
fee_rates:
operation: median
min: 0
max: 200
outgoing_base_fees:
base_fees:
operation: range
max: 1
block_height:
Expand Down
2 changes: 1 addition & 1 deletion examples/conditional.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ policies:
min: 100_000_000
node:
channels:
outgoing_fee_rates:
fee_rates:
operation: median
max: 1000
9 changes: 5 additions & 4 deletions examples/disabled_channels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ policies:
-
node:
channels:
incoming_disabled:
disabled:
operation: mean
max: 0.05
peers:
disabled:
operation: mean
max: 0.1
outgoing_disabled:
operation: mean
max: 0.05
2 changes: 1 addition & 1 deletion examples/stat_range.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ policies:
-
node:
channels:
outgoing_fee_rates:
fee_rates:
operation: median
min: 0
max: 100
105 changes: 58 additions & 47 deletions policy/channels.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,32 @@ import (

// Channels represents a set of requirements that the initiator's node channels must satisfy.
type Channels struct {
Number *Range[uint32] `yaml:"number,omitempty"`
Capacity *StatRange[int64] `yaml:"capacity,omitempty"`
ZeroBaseFees *bool `yaml:"zero_base_fees,omitempty"`
BlockHeight *StatRange[uint32] `yaml:"block_height,omitempty"`
TimeLockDelta *StatRange[uint32] `yaml:"time_lock_delta,omitempty"`
MinHTLC *StatRange[int64] `yaml:"min_htlc,omitempty"`
MaxHTLC *StatRange[uint64] `yaml:"max_htlc,omitempty"`
LastUpdateDiff *StatRange[uint32] `yaml:"last_update_diff,omitempty"`
Together *Range[int] `yaml:"together,omitempty"`
IncomingFeeRates *StatRange[int64] `yaml:"incoming_fee_rates,omitempty"`
OutgoingFeeRates *StatRange[int64] `yaml:"outgoing_fee_rates,omitempty"`
IncomingBaseFees *StatRange[int64] `yaml:"incoming_base_fees,omitempty"`
OutgoingBaseFees *StatRange[int64] `yaml:"outgoing_base_fees,omitempty"`
IncomingDisabled *StatRange[float64] `yaml:"incoming_disabled,omitempty"`
OutgoingDisabled *StatRange[float64] `yaml:"outgoing_disabled,omitempty"`
IncomingInboundFeeRates *StatRange[int32] `yaml:"incoming_inbound_fees_rates,omitempty"`
OutgoingInboundFeeRates *StatRange[int32] `yaml:"outgoing_inbound_fees_rates,omitempty"`
IncomingInboundBaseFees *StatRange[int32] `yaml:"incoming_inbound_base_fees,omitempty"`
OutgoingInboundBaseFees *StatRange[int32] `yaml:"outgoing_inbound_base_fees,omitempty"`
Number *Range[uint32] `yaml:"number,omitempty"`
Capacity *StatRange[int64] `yaml:"capacity,omitempty"`
ZeroBaseFees *bool `yaml:"zero_base_fees,omitempty"`
BlockHeight *StatRange[uint32] `yaml:"block_height,omitempty"`
TimeLockDelta *StatRange[uint32] `yaml:"time_lock_delta,omitempty"`
MinHTLC *StatRange[int64] `yaml:"min_htlc,omitempty"`
MaxHTLC *StatRange[uint64] `yaml:"max_htlc,omitempty"`
LastUpdateDiff *StatRange[uint32] `yaml:"last_update_diff,omitempty"`
Together *Range[int] `yaml:"together,omitempty"`
FeeRates *StatRange[int64] `yaml:"fee_rates,omitempty"`
BaseFees *StatRange[int64] `yaml:"base_fees,omitempty"`
Disabled *StatRange[float64] `yaml:"disabled,omitempty"`
InboundFeeRates *StatRange[int32] `yaml:"inbound_fees_rates,omitempty"`
InboundBaseFees *StatRange[int32] `yaml:"inbound_base_fees,omitempty"`
Peers *Peers `yaml:"peers,omitempty"`
}

// Peers contains information about the initiator node channels peers.
//
// Fields must be duplicated to follow the YAML structure desired.
type Peers struct {
FeeRates *StatRange[int64] `yaml:"fee_rates,omitempty"`
BaseFees *StatRange[int64] `yaml:"base_fees,omitempty"`
Disabled *StatRange[float64] `yaml:"disabled,omitempty"`
InboundFeeRates *StatRange[int32] `yaml:"inbound_fees_rates,omitempty"`
InboundBaseFees *StatRange[int32] `yaml:"inbound_base_fees,omitempty"`
}

func (c *Channels) evaluate(nodePublicKey string, peer *lnrpc.NodeInfo) error {
Expand Down Expand Up @@ -71,44 +78,48 @@ func (c *Channels) evaluate(nodePublicKey string, peer *lnrpc.NodeInfo) error {
return errors.New("Channels together " + c.Together.Reason())
}

if !checkStat(c.IncomingFeeRates, peer, feeRatesFunc(false)) {
return errors.New("Incoming fee rates " + c.IncomingFeeRates.Reason())
if !checkStat(c.FeeRates, peer, feeRatesFunc(true)) {
return errors.New("Channels fee rates " + c.FeeRates.Reason())
}

if !checkStat(c.OutgoingFeeRates, peer, feeRatesFunc(true)) {
return errors.New("Outgoing fee rates " + c.OutgoingFeeRates.Reason())
if !checkStat(c.BaseFees, peer, baseFeesFunc(true)) {
return errors.New("Channels base fees " + c.BaseFees.Reason())
}

if !checkStat(c.IncomingBaseFees, peer, baseFeesFunc(false)) {
return errors.New("Incoming base fees " + c.IncomingBaseFees.Reason())
if !checkStat(c.InboundFeeRates, peer, inboundFeeRatesFunc(true)) {
return errors.New("Channels inbound fee rates " + c.InboundFeeRates.Reason())
}

if !checkStat(c.OutgoingBaseFees, peer, baseFeesFunc(true)) {
return errors.New("Outgoing base fees " + c.OutgoingBaseFees.Reason())
if !checkStat(c.InboundBaseFees, peer, inboundBaseFeesFunc(true)) {
return errors.New("Channels inbound base fees " + c.InboundBaseFees.Reason())
}

if !checkStat(c.IncomingInboundFeeRates, peer, inboundFeeRatesFunc(false)) {
return errors.New("Incoming inbound fee rates " + c.IncomingInboundFeeRates.Reason())
if !c.checkDisabled(peer) {
return errors.New("Disabled channels " + c.Disabled.Reason())
}

if c.Peers == nil {
return nil
}

if !checkStat(c.OutgoingInboundFeeRates, peer, inboundFeeRatesFunc(true)) {
return errors.New("Outgoing inbound fee rates " + c.OutgoingInboundFeeRates.Reason())
if !checkStat(c.Peers.FeeRates, peer, feeRatesFunc(false)) {
return errors.New("Peers fee rates " + c.Peers.FeeRates.Reason())
}

if !checkStat(c.IncomingInboundBaseFees, peer, inboundBaseFeesFunc(false)) {
return errors.New("Incoming inbound base fees " + c.IncomingInboundBaseFees.Reason())
if !checkStat(c.Peers.BaseFees, peer, baseFeesFunc(false)) {
return errors.New("Peers base fees " + c.Peers.BaseFees.Reason())
}

if !checkStat(c.OutgoingInboundBaseFees, peer, inboundBaseFeesFunc(true)) {
return errors.New("Outgoing inbound base fees " + c.OutgoingInboundBaseFees.Reason())
if !checkStat(c.Peers.InboundFeeRates, peer, inboundFeeRatesFunc(false)) {
return errors.New("Peers inbound fee rates " + c.Peers.InboundFeeRates.Reason())
}

if !c.checkIncomingDisabled(peer) {
return errors.New("Incoming disabled channels " + c.IncomingDisabled.Reason())
if !checkStat(c.Peers.InboundBaseFees, peer, inboundBaseFeesFunc(false)) {
return errors.New("Peers inbound base fees " + c.Peers.InboundBaseFees.Reason())
}

if !c.checkOutgoingDisabled(peer) {
return errors.New("Outgoing disabled channels " + c.OutgoingDisabled.Reason())
if !c.checkPeersDisabled(peer) {
return errors.New("Peers disabled channels " + c.Peers.Disabled.Reason())
}

return nil
Expand Down Expand Up @@ -144,38 +155,38 @@ func (c *Channels) checkTogether(nodePublicKey string, peer *lnrpc.NodeInfo) boo
return c.Together.Contains(count)
}

func (c *Channels) checkIncomingDisabled(peer *lnrpc.NodeInfo) bool {
if c.IncomingDisabled == nil {
func (c *Channels) checkDisabled(peer *lnrpc.NodeInfo) bool {
if c.Disabled == nil {
return true
}

disabledChannels := make([]float64, len(peer.Channels))
for i, channel := range peer.Channels {
policy := getNodePolicy(peer.Node.PubKey, channel, false)
policy := getNodePolicy(peer.Node.PubKey, channel, true)

if policy.Disabled {
disabledChannels[i] = 1
}
}

return c.IncomingDisabled.Contains(disabledChannels)
return c.Disabled.Contains(disabledChannels)
}

func (c *Channels) checkOutgoingDisabled(peer *lnrpc.NodeInfo) bool {
if c.OutgoingDisabled == nil {
func (c *Channels) checkPeersDisabled(peer *lnrpc.NodeInfo) bool {
if c.Peers.Disabled == nil {
return true
}

disabledChannels := make([]float64, len(peer.Channels))
for i, channel := range peer.Channels {
policy := getNodePolicy(peer.Node.PubKey, channel, true)
policy := getNodePolicy(peer.Node.PubKey, channel, false)

if policy.Disabled {
disabledChannels[i] = 1
}
}

return c.OutgoingDisabled.Contains(disabledChannels)
return c.Peers.Disabled.Contains(disabledChannels)
}

func getNodePolicy(peerPublicKey string, channel *lnrpc.ChannelEdge, outgoing bool) *lnrpc.RoutingPolicy {
Expand Down
Loading

0 comments on commit da721be

Please sign in to comment.