lrc

package module
v0.0.0-...-e87ae62 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2024 License: MIT Imports: 10 Imported by: 0

README

Local Resource Conservation

Golang implementation of BOLTs/1071

This code is an untested POC and near-certainly contains bugs.

Documentation

Index

Constants

View Source
const MaxMilliSatoshi = 21_000_000 * 10_000_0000 * 1000

MaxMilliSatoshi is the maximum amount of millisatoshi that can possibly exist given 21 million bitcoin cap.

Variables

View Source
var (
	// ErrResolutionNotFound is returned when we get a resolution for a
	// HTLC that is not found in our in flight set.
	ErrResolutionNotFound = errors.New("resolved htlc not found")

	// ErrDuplicateIndex is returned when an incoming htlc index is
	// duplicated.
	ErrDuplicateIndex = errors.New("htlc index duplicated")
)
View Source
var (
	// ErrProtocolLimit is returned when we exceed the protocol defined
	// limit of htlc slots.
	ErrProtocolLimit = errors.New("slot count exceeds protocol limit of " +
		"483")

	// ErrProtectedPercentage is returned when a protected percentage
	// is invalid.
	ErrProtectedPercentage = errors.New("protected percentage must be " +
		"<= 100")
)
View Source
var (
	// ErrAmtOverflow indicates that a HTLC's amount is more than the
	// maximum theoretical number of millisatoshis.
	ErrAmtOverflow = errors.New("htlc amount overflows max msat")
)
View Source
var (
	// ErrChannelNotFound is returned when we don't have a channel
	// tracked in our internal state.
	ErrChannelNotFound = errors.New("channel not found")
)
View Source
var (
	// ErrResolvedNoResources is returned if we try to resolve a htlc on
	// the outgoing link that was not supposed to be allocated resources
	// in the first place.
	ErrResolvedNoResources = errors.New("resolved htlc on outgoing link " +
		"that should not have been assigned resources")
)

Functions

func BootstrapNetwork

func BootstrapNetwork(params ManagerParams, history []*NetworkForward,
	clock clock.Clock) (map[string]*ChannelBootstrap, error)

BootstrapNetwork reads a list of forwards belonging to a network of nodes and calculates pairwise reputation for all channels in the network.

Types

type ChannelBootstrap

type ChannelBootstrap struct {
	Incoming map[lnwire.ShortChannelID]*decayingAverage
	Outgoing map[lnwire.ShortChannelID]*decayingAverage
}

type ChannelFetcher

type ChannelFetcher func(lnwire.ShortChannelID) (*ChannelInfo, error)

type ChannelInfo

type ChannelInfo struct {
	// InFlightHTLC is the total number of htlcs allowed in flight.
	InFlightHTLC uint64

	// InFlightLiquidity is the total amount of liquidity allowed in
	// flight.
	InFlightLiquidity lnwire.MilliSatoshi
}

ChannelInfo provides information about a channel's routing restrictions.

type DecayingAverageStart

type DecayingAverageStart struct {
	LastUpdate time.Time
	Value      float64
}

DecayingAverageStart represents an optional start value to create a decaying average with.

func BootstrapReputation

func BootstrapReputation(scid lnwire.ShortChannelID, params ManagerParams,
	history []*ForwardedHTLC, clock clock.Clock) (*DecayingAverageStart,
	error)

BootstrapReputation processes a set of forwards where we are the incoming link and returns a start value for our reputation decaying average (or nil if there is no history).

func BootstrapRevenue

func BootstrapRevenue(scid lnwire.ShortChannelID, params ManagerParams,
	history []*ForwardedHTLC, clock clock.Clock) (*DecayingAverageStart,
	error)

BootstrapRevenue processes a set of forwards where we are the outgoing link and returns a start value for our revenue decaying average (or nil if there is no history).

type Endorsement

type Endorsement uint8

Endorsement represents the endorsement signaling that is passed along with a HTLC.

const (
	// EndorsementNone indicates that the TLV was not present.
	EndorsementNone Endorsement = iota

	// EndorsementFalse indicates that the TLV was present with a zero
	// value.
	EndorsementFalse

	// EndorsementTrue indicates that the TLV was present with a non-zero
	// value.
	EndorsementTrue
)

func NewEndorsementSignal

func NewEndorsementSignal(endorse bool) Endorsement

NewEndorsementSignal returns the enum representation of a boolean endorsement.

func (Endorsement) String

func (e Endorsement) String() string

type ForwardDecision

type ForwardDecision struct {
	// ReputationCheck contains the numerical values used in making a
	// reputation decision. This value will be non-nil
	ReputationCheck

	// ForwardOutcome is the action that the caller should take.
	ForwardOutcome
}

ForwardDecision contains the action that should be taken for forwarding a HTLC and debugging details of the values used.

type ForwardOutcome

type ForwardOutcome int

ForwardOutcome represents the various forwarding outcomes for a proposed HTLC forward.

const (
	// ForwardOutcomeNoResources means that a HTLC should be dropped
	// because the resource bucket that it qualifies for is full.
	ForwardOutcomeNoResources ForwardOutcome = iota

	// ForwardOutcomeUnendorsed means that the HTLC should be forwarded but
	// not endorsed.
	ForwardOutcomeUnendorsed

	// ForwardOutcomeEndorsed means that the HTLC should be forwarded
	// with a positive endorsement signal.
	ForwardOutcomeEndorsed
)

func (ForwardOutcome) String

func (f ForwardOutcome) String() string

type ForwardedHTLC

type ForwardedHTLC struct {
	// InFlightHTLC contains the original forwarding details of the HTLC.
	InFlightHTLC

	// Resolution contains the details of the HTLC's resolution if it has
	// been finally settled or failed. If the HTLC is still in flight, this
	// field should be nil.
	Resolution *ResolvedHTLC
}

ForwardedHTLC represents a HTLC that our node has previously forwarded.

type InFlightHTLC

type InFlightHTLC struct {
	// TimestampAdded is the time at which the incoming HTLC was added to
	// the incoming channel.
	TimestampAdded time.Time

	// OutgoingDecision indicates what resource allocation was assigned to
	// the outgoing htlc.
	OutgoingDecision ForwardOutcome

	// ProposedHTLC contains the original details of the HTLC that was
	// forwarded to us.
	// TODO: We probably don't need to store all of this info.
	*ProposedHTLC
}

InFlightHTLC tracks a HTLC forward that is currently in flight.

type IncomingReputation

type IncomingReputation struct {
	// IncomingRevenue represents the reputation that the forwarding
	// channel has accrued over time.
	IncomingRevenue float64

	// InFlightRisk represents the outstanding risk of all of the
	// forwarding party's currently in flight HTLCs.
	InFlightRisk float64
}

type LocalResourceManager

type LocalResourceManager interface {
	// ForwardHTLC updates the reputation manager to reflect that a
	// proposed HTLC has been forwarded. It requires the forwarding
	// restrictions of the outgoing channel to implement bucketing
	// appropriately.
	ForwardHTLC(htlc *ProposedHTLC, info *ChannelInfo) (*ForwardDecision,
		error)

	// ResolveHTLC updates the reputation manager to reflect that an
	// in-flight htlc has been resolved. It returns the in flight HTLC as
	// tracked by the manager. It will error if the HTLC is not found.
	//
	// Note that this API expects resolutions to be reported for *all*
	// HTLCs, even if the decision for ForwardHTLC was that we have no
	// resources for the forward - this function must still be used to
	// indicate that the HTLC has been cleared from our state (as it would
	// have been locked in on our incoming link).
	ResolveHTLC(htlc *ResolvedHTLC) (*InFlightHTLC, error)
}

LocalResourceManager is an interface representing an entity that tracks the reputation of channel peers based on HTLC forwarding behavior.

type Logger

type Logger interface {
	Infof(template string, args ...interface{})
	Debugf(template string, args ...interface{})
}

Very basic logger interface so that calling code can provide us with logging

type LookupReputation

type LookupReputation func(id lnwire.ShortChannelID) (*DecayingAverageStart,
	error)

LookupReputation is the function signature for fetching a decaying average start value for the give channel's reputation. If not history is available it is expected to return nil.

type LookupRevenue

type LookupRevenue func(id lnwire.ShortChannelID) (*DecayingAverageStart,
	error)

LookupReputation is the function signature for fetching a decaying average start value for the give channel's reputation. If not history is available it is expected to return nil.

type ManagerParams

type ManagerParams struct {
	// RevenueWindow is the amount of time that we examine the revenue of
	// outgoing links over.
	RevenueWindow time.Duration

	// ReputationMultiplier is the multiplier on RevenueWindow that is
	// used to determine the longer period of time that incoming links
	// reputation is assessed over.
	ReputationMultiplier uint8

	// ProtectedPercentage is the percentage of liquidity and slots that
	// are reserved for high reputation, endorsed HTLCs.
	ProtectedPercentage uint64

	// ResolutionPeriod is the amount of time that we reasonably expect
	// HTLCs to complete within.
	ResolutionPeriod time.Duration

	// BlockTime is the expected block time.
	BlockTime time.Duration
}

type MockBucket

type MockBucket struct {
	mock.Mock
}

MockClock implements the `clock.Clock` interface.

type MockReputation

type MockReputation struct {
	mock.Mock
}

func (*MockReputation) AddInFlight

func (m *MockReputation) AddInFlight(htlc *ProposedHTLC,
	outgoingDecision ForwardOutcome) error

func (*MockReputation) IncomingReputation

func (m *MockReputation) IncomingReputation() IncomingReputation

func (*MockReputation) ResolveInFlight

func (m *MockReputation) ResolveInFlight(htlc *ResolvedHTLC) (*InFlightHTLC,
	error)

type MockTarget

type MockTarget struct {
	mock.Mock
}

MockTarget mocks out revenueMontior.

func (*MockTarget) AddInFlight

func (m *MockTarget) AddInFlight(incomingReputation IncomingReputation,
	htlc *ProposedHTLC) ForwardDecision

func (*MockTarget) ResolveInFlight

func (m *MockTarget) ResolveInFlight(htlc *ResolvedHTLC,
	inFlight *InFlightHTLC) error

type NetworkForward

type NetworkForward struct {
	NodeAlias string
	*ForwardedHTLC
}

type NewReputationMonitor

type NewReputationMonitor func(start *DecayingAverageStart) reputationMonitor

NewReputationMonitor is a function signature for a constructor that creates a new reputation monitor.

type NewTargetMonitor

type NewTargetMonitor func(start *DecayingAverageStart,
	chanInfo *ChannelInfo) (targetMonitor, error)

NewTargetMonitor is a function signature for a constructor that creates a new target channel revenue monitor.

type ProposedHTLC

type ProposedHTLC struct {
	// IncomingChannel is the channel that has sent this htlc to the local
	// node for forwarding.
	IncomingChannel lnwire.ShortChannelID

	// OutgoingChannel is the outgoing channel that the sending node has
	// requested.
	OutgoingChannel lnwire.ShortChannelID

	// IncomingIndex is the HTLC index on the incoming channel.
	IncomingIndex int

	// IncomingEndorsed indicates whether the incoming channel forwarded
	// this HTLC as endorsed.
	IncomingEndorsed Endorsement

	// IncomingAmount is the amount of the HTLC on the incoming channel.
	IncomingAmount lnwire.MilliSatoshi

	// OutgoingAmount is the amount of the HTLC on the outgoing channel.
	OutgoingAmount lnwire.MilliSatoshi

	// CltvExpiryDelta is the difference between the block height at which
	// the HTLC was forwarded and its outgoing_cltv_expiry.
	CltvExpiryDelta uint32
}

ProposedHTLC provides information about a HTLC has has been locked in on our incoming channel, but not yet forwarded.

func (*ProposedHTLC) ForwardingFee

func (p *ProposedHTLC) ForwardingFee() lnwire.MilliSatoshi

ForwardingFee returns the fee paid by a htlc.

type ReputationCheck

type ReputationCheck struct {
	// IncomingReputation represents the reputation that has been built
	// up by the incoming link, and any outstanding risk that it poses to
	// us.
	IncomingReputation

	// OutgoingRevenue represents the cost of using the outgoing link,
	// evaluated based on how valuable it has been to us in the past.
	OutgoingRevenue float64

	// HTLCRisk represents the risk of the newly proposed HTLC, should it
	// be used to jam our channel for its full expiry time.
	HTLCRisk float64
}

ReputationCheck provides the reputation scores that are used to make a forwarding decision for a HTLC. These are surfaced for the sake of debugging and simulation, and wouldn't really be used much in a production implementation.

func (*ReputationCheck) String

func (r *ReputationCheck) String() string

String for a ReputationCheck.

func (*ReputationCheck) SufficientReputation

func (r *ReputationCheck) SufficientReputation() bool

SufficientReputation returns a boolean indicating whether a HTLC meets the reputation bar to be forwarded with endorsement.

type ResolvedHTLC

type ResolvedHTLC struct {
	// TimestampSettled is the time at which a htlc was resolved.
	TimestampSettled time.Time

	// IncomingIndex is the HTLC ID on the incoming link.
	IncomingIndex int

	// IncomingChannel is the short channel ID of the channel that
	// originally forwarded the incoming HTLC.
	IncomingChannel lnwire.ShortChannelID

	// OutgoingIndex is the HTLC ID on the outgoing link. Note that HTLCs
	// that fail locally won't have this value assigned.
	OutgoingIndex int

	// OutgoingChannel is the short channel ID of the channel that
	// forwarded the outgoing HTLC.
	OutgoingChannel lnwire.ShortChannelID

	// Success is true if the HTLC was fulfilled.
	Success bool
}

ResolvedHTLC summarizes the resolution of an in-flight HTLC.

type ResourceManager

type ResourceManager struct {

	// A single mutex guarding access to the manager.
	sync.Mutex
	// contains filtered or unexported fields
}

ResourceManager tracks local reputation earned by incoming channels, and the thresholds required to earn endorsement on the outgoing channels required to implement resource bucketing for a node's channels.

func NewResourceManager

func NewResourceManager(params ManagerParams, clock clock.Clock,
	lookupReputation LookupReputation,
	lookupRevenue LookupRevenue, log Logger) (*ResourceManager, error)

NewResourceManager creates a local reputation manager that will track channel revenue over the window provided, and incoming channel reputation over the window scaled by the multiplier.

func (*ResourceManager) ForwardHTLC

func (r *ResourceManager) ForwardHTLC(htlc *ProposedHTLC,
	chanOutInfo *ChannelInfo) (*ForwardDecision, error)

ForwardHTLC returns a boolean indicating whether the HTLC proposed is allowed to proceed based on its reputation, endorsement and resources available on the outgoing channel. If this function returns true, the HTLC has been added to internal state and must be cleared out using ResolveHTLC. If it returns false, it assumes that the HTLC will be failed back and does not expect any further resolution notification.

func (*ResourceManager) ResolveHTLC

func (r *ResourceManager) ResolveHTLC(htlc *ResolvedHTLC) (*InFlightHTLC,
	error)

ResolveHTLC updates the reputation manager's state to reflect the resolution. If the incoming channel or the in flight HTLC are not found this operation is a no-op. TODO: figure out whether we should allow this API to be called and then the corresponding forward is not found (depends on replay logic).

type TestLogger

type TestLogger struct{}

func (*TestLogger) Debugf

func (t *TestLogger) Debugf(template string, args ...interface{})

func (*TestLogger) Infof

func (t *TestLogger) Infof(template string, args ...interface{})

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL