lntransport

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 8, 2022 License: MIT Imports: 20 Imported by: 0

README

Go Reference

lntransport

An object that can dial and listen for Bitcoin Lightning Network (LN) connections. The connection objects send/receive messages with a simple API that uses context.Context.

All is safe for concurrent use.

Import

	lntransport "github.com/joakimofv/lntransport"

Usage

New
cfg := lntransport.Config{}
copy(cfg.Privkey[:], privkeyByteSlice)
lt, err := lntransport.New(cfg)
if err != nil {
	// Handle err.
}
defer lt.Close()

Privkey is a [32]byte array that needs to be a valid cryptographic key. See Config.

Listen
ch, addr, err := lt.Listen(ctx, "127.0.0.1:12345")

Cancelling the ctx will abort the background listening process.

Incoming connections will be passed on the ch channel. The channel will be closed when the listener is done so you can drain it like this:

var conn *Conn
for conn = range ch {
	defer conn.Close()
	// ...
}
Dial
conn, err := lt.Dial(ctx, "1.2.3.4:12345", remotePubkey)
if err != nil {
	// Handle err.
}
defer conn.Close()

The remotePubkey refers to the pubkey of the remote side, a byte slice, which you have to learn somehow before dialing. For your own side you can get it with lt.Pubkey().

Send
err := conn.Send(ctx, []byte("abcd..."))
if err != nil {
	if conn.IsClosed() {
		// conn has become defunct.
	}
	// Handle err.
}
Receive
msg, err := conn.Receive(ctx)
if err != nil {
	if conn.IsClosed() {
		// conn has become defunct.
	}
	// Handle err.
}

Error Handling

Defunct Connection

Various network problems, counterparty problems, or bungled sends/receives may cause a connection object to become defunct. Then it will close itself. Check if it has happened with conn.IsClosed().

A closed connection can not be recovered. Be ready to dial again to make a new connection, or handle the situation in some other way.

Failed Incoming Connection Attempts

Incoming connection attempts to a listener may fail. By default, when it happens a line will be printed with stdlib log. Adjust what is done with these errors through fields in the Config.

Limit On Number Of Connections

Having more than 30 000 connection object active from a single LnTransport can cause it to malfunction. Avoid that.

Documentation

Overview

Package lntransport provides a connection object for encrypted tcp communication on Bitcoin Lightning Network.

Index

Constants

View Source
const (
	// HandshakeVersion is the expected version of the protocol handshake.
	// Any messages that carry a different version will cause the handshake
	// to abort immediately.
	HandshakeVersion = byte(0)
)

Variables

View Source
var ErrConnClosed = errors.New("use of closed Conn")
View Source
var ErrLnTransportClosed = errors.New("use of closed LnTransport")
View Source
var ErrMaxMessageLengthExceeded = fmt.Errorf("the generated payload exceeds the max allowed message length of %d", math.MaxUint16)

ErrMaxMessageLengthExceeded is returned when a message to be written to the cipher session exceeds the maximum allowed message payload.

Functions

This section is empty.

Types

type AuthError

type AuthError struct {
	Err            error
	RemoteAddrPort netip.AddrPort
}

AuthError may be passed on Config.ListenErrChan.

func (AuthError) Error

func (err AuthError) Error() string

func (AuthError) Unwrap

func (err AuthError) Unwrap() error

type Config

type Config struct {
	// Private key in bytes, used to encrypt the transport.
	//
	// The empty value won't work, it needs to be a valid secp256k1 key.
	// Tip: Use github.com/btcsuite/btcd/btcec/v2 NewPrivateKey() Serialize() to get something valid for testing etc.
	Privkey [32]byte

	// Number of incoming connection attempts that can be handled in parallel by the goroutine spawned by Listen.
	// Default: 10
	MaxParallelListenHandshakes int

	// Whether to disable logging.
	// If left at false (default) then will use stdlib log to print non-critical errors from Listen goroutines,
	// such as failed incoming connection attempts.
	ListenErrNoLog bool

	// ListenErrChan, if set to non-nil, will have non-critical errors passed to it,
	// along with the address/port of the listener that encountered the error.
	// Concerns the same errors as ListenErrNoLog.
	// Can be useful for custom logging, or specific reactions to certain failed incoming connection attempts.
	//
	// Relevant error type checks:
	//   _, ok := elem.Err.(net.Error)  // ok==true means there was a net level connection problem during an incoming connection attempt.
	//   errors.As(err, &AuthError{})  // true means there was an cryptographic authentication problem during an incoming connection attempt.
	//   errors.Is(err, ErrLnTransportClosed)
	//   errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded)
	//
	// Note: You must keep this channel drained (or set to nil) or else components of LnTransport can get blocked waiting to send on it.
	//       Channel won't be closed by LnTransport when it is closed.
	ListenErrChan chan<- ErrAndAddrPort

	// ListenErrFunc works on errors like ListenErrChan, passes them to the given function, if non-nil.
	ListenErrFunc func(ea ErrAndAddrPort)
}

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is a network connection with transport encrypted according to the protocol.

Must be created through LnTransport.Dial or LnTransport.Listen. Close should be called to ensure resources are released.

Conn is safe for concurrent use by multiple goroutines. Sends and Receives are serialized so that only one of each will write/read on the network connection at a time.

func (*Conn) Close

func (conn *Conn) Close() error

Close closes the underlying network connection. Idempotent.

Any ongoing, or future, Send or Receive calls will be unblocked and return a non-nil error.

func (*Conn) IsClosed

func (conn *Conn) IsClosed() bool

IsClosed reports if the connection has been closed, either by a call to Close or due to becoming defunct after a failed Send/Receive.

func (*Conn) LocalAddrPort

func (conn *Conn) LocalAddrPort() netip.AddrPort

LocalAddrPort returns the local network address.

func (*Conn) LocalPubkey

func (conn *Conn) LocalPubkey() [33]byte

LocalPubkey returns the own static public key.

func (*Conn) Receive

func (conn *Conn) Receive(ctx context.Context) ([]byte, error)

Receive reads the next message on the connection and returns it as a slice of bytes. Blocks until a message arrives, the Conn or LnTransport is closed, or the context expires.

The returned byte slice is not safe for use after Receive is called again, the underlying storage will be reused on the next read.

A non-nil error means that a message was not fully received (and a partial message won't be returned). Then the connection might have been closed. Check for it with IsClosed. Comparing the returned error to ErrConnClosed is not enough.

If the remote side closed the connection during the receive then the returned error will contain io.EOF (check with errors.Is).

func (*Conn) RemoteAddrPort

func (conn *Conn) RemoteAddrPort() netip.AddrPort

RemoteAddrPort returns the remote network address.

func (*Conn) RemotePubkey

func (conn *Conn) RemotePubkey() [33]byte

RemotePubkey returns the remote peer's static public key.

func (*Conn) Send

func (conn *Conn) Send(ctx context.Context, msg []byte) error

Send writes the next message to the connection. Blocks until the whole message is written, the Conn or LnTransport is closed, or the context expires.

A non-nil error guarantees that the message was not fully sent. Then, in case there was a partial send, the connection may become defunct and is closed. Check for it with IsClosed. Comparing the returned error to ErrConnClosed is not enough.

You must then dial up a new connection and send the message on that, if you want to proceed with the send.

If the connection was not closed then inspect the error to see if it is recoverable by doing another send on the same connection. Known unrecoverable errors: ErrMaxMessageLengthExceeded

type ErrAndAddrPort

type ErrAndAddrPort struct {
	Err      error
	AddrPort netip.AddrPort
}

ErrAndAddrPort used in Config.ListenErrChan, see comment there.

type LnTransport

type LnTransport struct {
	// contains filtered or unexported fields
}

LnTransport is an object which can listen for and/or dial up connections with the transport protocol specified by https://github.com/lightning/bolts/blob/master/08-transport.md

Must be created with New. Close must be called to ensure resources are released.

LnTransport is safe for concurrent use by multiple goroutines.

func New

func New(cfg Config) (*LnTransport, error)

New validates the Config and uses it to create a LnTransport.

func (*LnTransport) Close

func (lt *LnTransport) Close() error

Close stops spawned goroutines, including listeners. Idempotent.

Future calls to Dial or Listen will return ErrLnTransportClosed.

All Conns that have been generated by LnTransport will on Send/Receive be closed and return ErrLnTransportClosed.

func (*LnTransport) Dial

func (lt *LnTransport) Dial(ctx context.Context, address string, remotePubkey []byte, options ...func(*net.Dialer)) (*Conn, error)

Dial attempts to make an outgoing connection.

Cancelling the context aborts the connection attempt, but has no effect on a successfully returned connection.

See func net.Dialer.DialContext for a description of the address parameter. The network is "tcp".

remotePubkey is the pubkey that the remote party uses for transport encryption. About the format of remotePubkey, see pkg.go.dev/github.com/decred/dcrd/dcrec/secp256k1/v4#ParsePubKey

func (*LnTransport) Listen

func (lt *LnTransport) Listen(ctx context.Context, address string, options ...func(*net.ListenConfig)) (chan *Conn, netip.AddrPort, error)

Listen handles incoming connection attempts. It returns a channel whereupon successful connections will be passed, and the local listening address. The channel will be closed when the listening is stopped.

Cancelling the context stops the listening for new connections, but has no effect on successfully returned connections. Closing the LnTransport is another way to stop the listening.

See func net.ListenConfig.Listen for a description of the address parameter. The network is "tcp".

func (*LnTransport) Pubkey

func (lt *LnTransport) Pubkey() [33]byte

Pubkey returns the public key that corresponds to the private key that LnTransport was created with.

Jump to

Keyboard shortcuts

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