peer

package
v1.15.0 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2026 License: BSD-3-Clause Imports: 48 Imported by: 34

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrNoCertsSent        = errors.New("no certificates sent by peer")
	ErrEmptyCert          = errors.New("certificate sent by peer is empty")
	ErrEmptyPublicKey     = errors.New("no public key sent by peer")
	ErrCurveMismatch      = errors.New("only P256 is allowed for ECDSA")
	ErrUnsupportedKeyType = errors.New("key type is not supported")
)

Functions

func NoPrecondition

func NoPrecondition(*Peer) bool

NoPrecondition can be supplied to Set.Sample to indicate that all peers are eligible to be returned in the sample.

func TLSConfig

func TLSConfig(cert tls.Certificate, keyLogWriter io.Writer) *tls.Config

TLSConfig returns the TLS config that will allow secure connections to other peers.

It is safe, and typically expected, for [keyLogWriter] to be [nil]. [keyLogWriter] should only be enabled for debugging.

func ValidateCertificate added in v1.11.13

func ValidateCertificate(cs tls.ConnectionState) error

ValidateCertificate validates TLS certificates according their public keys on the leaf certificate in the certification chain.

Types

type Config

type Config struct {
	// Size, in bytes, of the buffer this peer reads messages into
	ReadBufferSize int
	// Size, in bytes, of the buffer this peer writes messages into
	WriteBufferSize int
	Clock           mockable.Clock
	Metrics         *Metrics
	MessageCreator  message.Creator

	Log                  logging.Logger
	InboundMsgThrottler  throttling.InboundMsgThrottler
	Network              Network
	Router               router.InboundHandler
	VersionCompatibility *version.Compatibility
	MyNodeID             ids.NodeID
	// MySubnets does not include the primary network ID
	MySubnets          set.Set[ids.ID]
	Beacons            validators.Manager
	Validators         validators.Manager
	NetworkID          uint32
	PingFrequency      time.Duration
	PongTimeout        time.Duration
	MaxClockDifference time.Duration

	SupportedACPs []uint32
	ObjectedACPs  []uint32

	// Unix time of the last message sent and received respectively
	// Must only be accessed atomically
	LastSent, LastReceived int64

	// Tracks CPU/disk usage caused by each peer.
	ResourceTracker tracker.ResourceTracker

	// Calculates uptime of peers
	UptimeCalculator uptime.Calculator

	// Signs my IP so I can send my signed IP address in the Handshake message
	IPSigner *IPSigner

	// IngressConnectionCount counts the ingress (to us) connections.
	IngressConnectionCount atomic.Int64

	// If true, connects to all validators regardless of primary network validator
	// status or of configured tracked subnets.
	ConnectToAllValidators bool
}

type IPSigner added in v1.9.4

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

IPSigner will return a signedIP for the current value of our dynamic IP.

func NewIPSigner added in v1.9.4

func NewIPSigner(
	ip *utils.Atomic[netip.AddrPort],
	tlsSigner crypto.Signer,
	blsSigner bls.Signer,
) *IPSigner

func (*IPSigner) GetSignedIP added in v1.9.4

func (s *IPSigner) GetSignedIP() (*SignedIP, error)

GetSignedIP returns the signedIP of the current value of the provided dynamicIP. If the dynamicIP hasn't changed since the prior call to GetSignedIP, then the same SignedIP will be returned.

It's safe for multiple goroutines to concurrently call GetSignedIP.

type Info

type Info struct {
	IP             netip.AddrPort  `json:"ip"`
	PublicIP       netip.AddrPort  `json:"publicIP,omitempty"`
	ID             ids.NodeID      `json:"nodeID"`
	Version        string          `json:"version"`
	UpgradeTime    uint64          `json:"upgradeTime"`
	LastSent       time.Time       `json:"lastSent"`
	LastReceived   time.Time       `json:"lastReceived"`
	ObservedUptime json.Uint32     `json:"observedUptime"`
	TrackedSubnets set.Set[ids.ID] `json:"trackedSubnets"`
	SupportedACPs  set.Set[uint32] `json:"supportedACPs"`
	ObjectedACPs   set.Set[uint32] `json:"objectedACPs"`
}

type MessageQueue added in v1.7.11

type MessageQueue interface {
	// Push attempts to add the message to the queue. If the context is
	// canceled, then pushing the message will return `false` and the message
	// will not be added to the queue.
	Push(ctx context.Context, msg *message.OutboundMessage) bool

	// Pop blocks until a message is available and then returns the message. If
	// the queue is closed, then `false` is returned.
	Pop() (*message.OutboundMessage, bool)
	// PopNow attempts to return a message without blocking. If a message is not
	// available or the queue is closed, then `false` is returned.
	PopNow() (*message.OutboundMessage, bool)

	// Close empties the queue and prevents further messages from being pushed
	// onto it. After calling close once, future calls to close will do nothing.
	Close()
}

func NewBlockingMessageQueue added in v1.7.11

func NewBlockingMessageQueue(
	onFailed SendFailedCallback,
	log logging.Logger,
	bufferSize int,
) MessageQueue

func NewThrottledMessageQueue added in v1.7.11

func NewThrottledMessageQueue(
	onFailed SendFailedCallback,
	id ids.NodeID,
	log logging.Logger,
	outboundMsgThrottler throttling.OutboundMsgThrottler,
) MessageQueue

type Metrics

type Metrics struct {
	ClockSkewCount prometheus.Counter
	ClockSkewSum   prometheus.Gauge

	RTTCount prometheus.Counter
	RTTSum   prometheus.Gauge

	NumFailedToParse prometheus.Counter
	NumSendFailed    *prometheus.CounterVec // op

	Messages   *prometheus.CounterVec // io + op + compressed
	Bytes      *prometheus.CounterVec // io + op
	BytesSaved *prometheus.GaugeVec   // io + op
}

func NewMetrics

func NewMetrics(registerer prometheus.Registerer) (*Metrics, error)

func (*Metrics) MultipleSendsFailed

func (m *Metrics) MultipleSendsFailed(op message.Op, count int)

func (*Metrics) Received

func (m *Metrics) Received(msg *message.InboundMessage, msgLen uint32)

func (*Metrics) SendFailed

func (m *Metrics) SendFailed(msg *message.OutboundMessage)

SendFailed updates the metrics for having failed to send [msg].

func (*Metrics) Sent

func (m *Metrics) Sent(msg *message.OutboundMessage)

Sent updates the metrics for having sent [msg].

type Network

type Network interface {
	// Connected is called by the peer once the handshake is finished.
	Connected(peerID ids.NodeID)

	// AllowConnection enables the network is signal to the peer that its
	// connection is no longer desired and should be terminated.
	AllowConnection(peerID ids.NodeID) bool

	// Track allows the peer to notify the network of potential new peers to
	// connect to.
	Track(ips []*ips.ClaimedIPPort) error

	// Disconnected is called when the peer finishes shutting down. It is not
	// guaranteed that [Connected] was called for the provided peer. However, it
	// is guaranteed that [Connected] will not be called after [Disconnected]
	// for a given [Peer] object.
	Disconnected(peerID ids.NodeID)

	// KnownPeers returns the bloom filter of the known peers.
	KnownPeers() (bloomFilter []byte, salt []byte)

	// Peers returns peers that are not known.
	Peers(
		peerID ids.NodeID,
		trackedSubnets set.Set[ids.ID],
		requestAllPeers bool,
		knownPeers *bloom.ReadFilter,
		peerSalt []byte,
	) []*ips.ClaimedIPPort
}

Network defines the interface that is used by a peer to help establish a well connected p2p network.

var TestNetwork Network = testNetwork{}

type Peer

type Peer struct {
	*Config
	// contains filtered or unexported fields
}

Peer encapsulates all of the functionality required to send and receive messages with a remote peer.

func Start

func Start(
	config *Config,
	conn net.Conn,
	cert *staking.Certificate,
	id ids.NodeID,
	messageQueue MessageQueue,
	isIngress bool,
) *Peer

Start a new peer instance.

Invariant: There must only be one peer running at a time with a reference to the same [config.InboundMsgThrottler].

func StartTestPeer

func StartTestPeer(
	ctx context.Context,
	ip netip.AddrPort,
	networkID uint32,
	router router.InboundHandler,
) (*Peer, error)

StartTestPeer provides a simple interface to create a peer that has finished the p2p handshake.

This function will generate a new TLS key to use when connecting to the peer.

The returned peer will not throttle inbound or outbound messages.

  • [ctx] provides a way of canceling the connection request.
  • [ip] is the remote that will be dialed to create the connection.
  • [networkID] will be sent to the peer during the handshake. If the peer is expecting a different [networkID], the handshake will fail and an error will be returned.
  • router will be called with all non-handshake messages received by the peer.
Example
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
defer cancel()

peerIP := netip.AddrPortFrom(
	netip.IPv6Loopback(),
	9651,
)
peer, err := StartTestPeer(
	ctx,
	peerIP,
	constants.LocalID,
	router.InboundHandlerFunc(func(_ context.Context, msg *message.InboundMessage) {
		fmt.Printf("handling %s\n", msg.Op)
	}),
)
if err != nil {
	panic(err)
}

// Send messages here with [peer.Send].

peer.StartClose()
err = peer.AwaitClosed(ctx)
if err != nil {
	panic(err)
}

func (*Peer) AwaitClosed

func (p *Peer) AwaitClosed(ctx context.Context) error

AwaitClosed will block until the peer has been fully shutdown. If the context is cancelled, then an error will be returned.

func (*Peer) AwaitReady

func (p *Peer) AwaitReady(ctx context.Context) error

AwaitReady will block until the peer has finished the p2p handshake. If the context is cancelled or the peer starts closing, then an error will be returned.

func (*Peer) Cert

func (p *Peer) Cert() *staking.Certificate

Cert returns the certificate that the remote peer is using to authenticate their messages.

func (*Peer) Closed

func (p *Peer) Closed() bool

Closed returns true once the peer has been fully shutdown. It is guaranteed that no more messages will be received by this peer once this returns true.

func (*Peer) ID

func (p *Peer) ID() ids.NodeID

ID returns the ids.NodeID of the remote peer.

func (*Peer) IP

func (p *Peer) IP() *SignedIP

IP returns the claimed IP and signature provided by this peer during the handshake. It should only be called after Peer.Ready returns true.

func (*Peer) Info

func (p *Peer) Info() Info

Info returns a description of the state of this peer. It should only be called after Peer.Ready returns true.

func (*Peer) LastReceived

func (p *Peer) LastReceived() time.Time

LastReceived returns the last time a message was received from the peer.

func (*Peer) LastSent

func (p *Peer) LastSent() time.Time

LastSent returns the last time a message was sent to the peer.

func (*Peer) ObservedUptime

func (p *Peer) ObservedUptime() uint32

ObservedUptime returns the local node's primary network uptime according to the peer. The value ranges from [0, 100]. It should only be called after Peer.Ready returns true.

func (*Peer) Ready

func (p *Peer) Ready() bool

Ready returns true if the peer has finished the p2p handshake and is ready to send and receive messages.

func (*Peer) Send

func (p *Peer) Send(ctx context.Context, msg *message.OutboundMessage) bool

Send attempts to send msg to the peer. The peer takes ownership of msg for reference counting. This returns false if the message is guaranteed not to be delivered to the peer.

func (*Peer) StartClose

func (p *Peer) StartClose()

StartClose will begin shutting down the peer. It will not block.

func (*Peer) StartSendGetPeerList added in v1.10.18

func (p *Peer) StartSendGetPeerList()

StartSendGetPeerList attempts to send a GetPeerList message to this peer on this peer's gossip routine. It is not guaranteed that a GetPeerList will be sent.

func (*Peer) TrackedSubnets

func (p *Peer) TrackedSubnets() set.Set[ids.ID]

TrackedSubnets returns the subnets this peer is running. It should only be called after Peer.Ready returns true.

func (*Peer) Version

func (p *Peer) Version() *version.Application

Version returns the claimed node version this peer is running. It should only be called after Peer.Ready returns true.

type SendFailedCallback added in v1.7.11

type SendFailedCallback interface {
	SendFailed(*message.OutboundMessage)
}

type SendFailedFunc added in v1.7.11

type SendFailedFunc func(*message.OutboundMessage)

func (SendFailedFunc) SendFailed added in v1.7.11

func (f SendFailedFunc) SendFailed(msg *message.OutboundMessage)

type Set

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

Set contains a group of peers.

func NewSet

func NewSet() *Set

NewSet returns a set that does not internally manage synchronization.

Only Set.Add and Set.Remove require exclusion on the data structure. The remaining methods are safe for concurrent use.

func (*Set) Add

func (s *Set) Add(peer *Peer)

Add this peer to the set.

If a peer with the same Peer.ID is already in the set, then the new peer instance will replace the old peer instance.

Add does not change the Peer.ID returned from calls to Set.GetByIndex.

func (*Set) AllInfo

func (s *Set) AllInfo() []Info

AllInfo returns information about all the peers.

func (*Set) GetByID

func (s *Set) GetByID(nodeID ids.NodeID) (*Peer, bool)

GetByID attempts to fetch a Peer whose Peer.ID is equal to nodeID. If no such peer exists in the set, then [false] will be returned.

func (*Set) GetByIndex

func (s *Set) GetByIndex(index int) (*Peer, bool)

GetByIndex attempts to fetch a Peer who has been allocated index. If index < 0 or index >= Set.Len, then false will be returned.

func (*Set) Info

func (s *Set) Info(nodeIDs []ids.NodeID) []Info

Info returns information about the requested peers if they are in the set.

func (*Set) Len

func (s *Set) Len() int

Len returns the number of peers currently in this set.

func (*Set) Remove

func (s *Set) Remove(nodeID ids.NodeID)

Remove any Peer whose Peer.ID is equal to nodeID from the set.

func (*Set) Sample

func (s *Set) Sample(n int, precondition func(*Peer) bool) []*Peer

Sample attempts to return a random slice of peers with length n. The slice will not include any duplicates. Only peers that cause the precondition to return true will be returned in the slice.

type SignedIP

type SignedIP struct {
	UnsignedIP
	TLSSignature      []byte
	BLSSignature      *bls.Signature
	BLSSignatureBytes []byte
}

SignedIP is a wrapper of an UnsignedIP with the signature from a signer.

func (*SignedIP) Verify added in v1.7.8

func (ip *SignedIP) Verify(
	cert *staking.Certificate,
	maxTimestamp time.Time,
) error

Returns nil if: * [ip.Timestamp] is not after [maxTimestamp]. * [ip.TLSSignature] is a valid signature over [ip.UnsignedIP] from [cert].

type UnsignedIP

type UnsignedIP struct {
	AddrPort  netip.AddrPort
	Timestamp uint64
}

UnsignedIP is used for a validator to claim an IP. The [Timestamp] is used to ensure that the most updated IP claim is tracked by peers for a given validator.

func (*UnsignedIP) Sign

func (ip *UnsignedIP) Sign(tlsSigner crypto.Signer, blsSigner bls.Signer) (*SignedIP, error)

Sign this IP with the provided signer and return the signed IP.

type Upgrader

type Upgrader interface {
	// Must be thread safe
	Upgrade(net.Conn) (ids.NodeID, net.Conn, *staking.Certificate, error)
}

func NewTLSClientUpgrader

func NewTLSClientUpgrader(config *tls.Config, invalidCerts prometheus.Counter) Upgrader

func NewTLSServerUpgrader

func NewTLSServerUpgrader(config *tls.Config, invalidCerts prometheus.Counter) Upgrader

Jump to

Keyboard shortcuts

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