protocols

package
v0.5.9-0...-ba7202b Latest Latest
Warning

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

Go to latest
Published: Mar 11, 2022 License: GPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package protocols is an extension to p2p. It offers a user friendly simple way to define devp2p subprotocols by abstracting away code standardly shared by protocols.

* automate assignments of code indexes to messages * automate RLP decoding/encoding based on reflecting * provide the forever loop to read incoming messages * standardise error handling related to communication * standardised handshake negotiation * TODO: automatic generation of wire protocol specification for peers

Index

Constants

View Source
const (
	// Sender declares that a message needs to be paid by the sender of the message
	Sender = Payer(true)
	// Receiver declares that a message needs to be paid by the receiver of the message
	Receiver = Payer(false)
)
View Source
const AccountingVersion = "1.0"

Textual version number of accounting API

Variables

This section is empty.

Functions

func Break

func Break(err error) error

Break wraps error and creates a special error that is treated specially in the protocol.Run event loop It causes protocol.Run event loop to be exit and drop the peer.

Types

type Accounting

type Accounting struct {
	Balance // interface to accounting logic
}

Accounting implements the Hook interface It interfaces to the balances through the Balance interface

func NewAccounting

func NewAccounting(balance Balance) *Accounting

NewAccounting creates a new instance of Accounting

func (*Accounting) Apply

func (ah *Accounting) Apply(peer *Peer, costToLocalNode int64, size uint32) error

Apply takes a peer, the signed cost for the local node and the msg size and credits/debits local node using balance interface

func (*Accounting) Validate

func (ah *Accounting) Validate(peer *Peer, size uint32, msg interface{}, payer Payer) (int64, error)

Validate calculates the cost for the local node sending or receiving a msg to/from a peer querying the message for its price. It returns either the signed cost for the local node as int64 or an error, signaling that the accounting operation would fail (no change has been applied at this point)

type AccountingApi

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

AccountingApi provides an API to access account related information

func NewAccountingApi

func NewAccountingApi(m *AccountingMetrics) *AccountingApi

NewAccountingApi creates a new AccountingApi m will be used to check if accounting metrics are enabled

func (*AccountingApi) Balance

func (self *AccountingApi) Balance() (int64, error)

Balance returns local node balance (units credited - units debited)

func (*AccountingApi) BalanceCredit

func (self *AccountingApi) BalanceCredit() (int64, error)

BalanceCredit returns total amount of units credited by local node

func (*AccountingApi) BalanceDebit

func (self *AccountingApi) BalanceDebit() (int64, error)

BalanceCredit returns total amount of units debited by local node

func (*AccountingApi) BytesCredit

func (self *AccountingApi) BytesCredit() (int64, error)

BytesCredit returns total amount of bytes credited by local node

func (*AccountingApi) BytesDebit

func (self *AccountingApi) BytesDebit() (int64, error)

BalanceCredit returns total amount of bytes debited by local node

func (*AccountingApi) MsgCredit

func (self *AccountingApi) MsgCredit() (int64, error)

MsgCredit returns total amount of messages credited by local node

func (*AccountingApi) MsgDebit

func (self *AccountingApi) MsgDebit() (int64, error)

MsgDebit returns total amount of messages debited by local node

func (*AccountingApi) PeerDrops

func (self *AccountingApi) PeerDrops() (int64, error)

PeerDrops returns number of times when local node had to drop remote peers

func (*AccountingApi) SelfDrops

func (self *AccountingApi) SelfDrops() (int64, error)

SelfDrops returns number of times when local node was overdrafted and dropped

type AccountingMetrics

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

AccountMetrics abstracts away the metrics DB and the reporter to persist metrics

func NewAccountingMetrics

func NewAccountingMetrics(r metrics.Registry, d time.Duration, path string) *AccountingMetrics

NewMetricsDB creates a new LevelDB instance used to persist metrics defined inside p2p/protocols/accounting.go

func SetupAccountingMetrics

func SetupAccountingMetrics(reportInterval time.Duration, path string) *AccountingMetrics

SetupAccountingMetrics uses a separate registry for p2p accounting metrics; this registry should be independent of any other metrics as it persists at different endpoints. It also starts the persisting go-routine which at the passed interval writes the metrics to a LevelDB

func (*AccountingMetrics) Close

func (am *AccountingMetrics) Close()

Close will be called when the node is being shutdown for a graceful cleanup

type Balance

type Balance interface {
	// Adds amount to the local balance with remote node `peer`;
	// positive amount = credit local node
	// negative amount = debit local node
	Add(amount int64, peer *Peer) error
	// Check is a dry-run for the Add operation:
	// As the accounting takes place **after** the actual send/receive operation happens,
	// we want to make sure that that operation would not result in any problem
	Check(amount int64, peer *Peer) error
}

Balance is the actual accounting instance Balance defines the operations needed for accounting Implementations internally maintain the balance for every peer

type Hook

type Hook interface {
	// A hook for applying accounting
	Apply(peer *Peer, costToLocalNode int64, size uint32) error
	// Run some validation before applying accounting
	Validate(peer *Peer, size uint32, msg interface{}, payer Payer) (int64, error)
}

For accounting, the design is to allow the Spec to describe which and how its messages are priced To access this functionality, we provide a Hook interface which will call accounting methods NOTE: there could be more such (horizontal) hooks in the future

type MsgPauser

type MsgPauser interface {
	Pause()
	Resume()
	Wait()
}

MsgPauser can be used to pause run execution IMPORTANT: should be used only for tests

type Payer

type Payer bool

Payer is the base type to define who pays in an exchange between peers

type Peer

type Peer struct {
	*p2p.Peer // the p2p.Peer object representing the remote
	// contains filtered or unexported fields
}

Peer represents a remote peer or protocol instance that is running on a peer connection with a remote peer

func NewPeer

func NewPeer(peer *p2p.Peer, rw p2p.MsgReadWriter, spec *Spec) *Peer

NewPeer constructs a new peer this constructor is called by the p2p.Protocol#Run function the first two arguments are the arguments passed to p2p.Protocol.Run function the third argument is the Spec describing the protocol

func (*Peer) Drop

func (p *Peer) Drop(reason string)

Drop disconnects a peer TODO: may need to implement protocol drop only? don't want to kick off the peer

func (*Peer) Handshake

func (p *Peer) Handshake(ctx context.Context, hs interface{}, verify func(interface{}) error) (interface{}, error)

Handshake negotiates a handshake on the peer connection * arguments

  • context
  • the local handshake to be sent to the remote peer
  • function to be called on the remote handshake (can be nil)

* expects a remote handshake back of the same type * the dialing peer needs to send the handshake first and then waits for remote * the listening peer waits for the remote handshake and then sends it returns the remote handshake and an error

func (*Peer) HasCap

func (p *Peer) HasCap(capName string) (yes bool)

HasCap returns true if Peer has a capability with provided name.

func (*Peer) Run

func (p *Peer) Run(handler func(ctx context.Context, msg interface{}) error) error

Run starts the forever loop that handles incoming messages. The handler argument is a function which is called for each message received from the remote peer, a returned error causes the loop to exit resulting in disconnection of the protocol

func (*Peer) Send

func (p *Peer) Send(ctx context.Context, msg interface{}) error

Send takes a message, encodes it in RLP, finds the right message code and sends the message off to the peer this low level call will be wrapped by libraries providing routed or broadcast sends but often just used to forward and push messages to directly connected peers

func (*Peer) SetMsgPauser

func (p *Peer) SetMsgPauser(pauser MsgPauser)

SetMsgPauser sets message pauser for this peer IMPORTANT: to be used only for testing

func (*Peer) Stop

func (p *Peer) Stop(timeout time.Duration) error

Stop stops the execution of new async jobs, and blocks until active jobs are finished or provided timeout passes. Returns nil if the active jobs are finished within the timeout duration, or error otherwise.

type Price

type Price struct {
	Value   uint64
	PerByte bool // True if the price is per byte or for unit
	Payer   Payer
}

Price represents the costs of a message

func (*Price) For

func (p *Price) For(payer Payer, size uint32) int64

For gives back the price for a message A protocol provides the message price in absolute value This method then returns the correct signed amount, depending on who pays, which is identified by the `payer` argument: Sending will pass a `Sender` payer, receiving will pass the `Receiver` argument. Thus: If Sending and sender pays, amount negative, otherwise positive If Receiving, and receiver pays, amount negative, otherwise positive

type PricedMessage

type PricedMessage interface {
	// Return the Price for a message
	Price() *Price
}

PricedMessage defines how a message type identifies itself as to be accounted

type Spec

type Spec struct {
	// Name is the name of the protocol, often a three-letter word
	Name string

	// Version is the version number of the protocol
	Version uint

	// MaxMsgSize is the maximum accepted length of the message payload
	MaxMsgSize uint32

	// Messages is a list of message data types which this protocol uses, with
	// each message type being sent with its array index as the code (so
	// [&foo{}, &bar{}, &baz{}] would send foo, bar and baz with codes
	// 0, 1 and 2 respectively)
	// each message must have a single unique data type
	Messages []interface{}

	//hook for accounting (could be extended to multiple hooks in the future)
	Hook Hook

	// if the protocol does not allow extending the p2p msg to propagate context
	// even if context not disabled, context will propagate only tracing is enabled
	DisableContext bool
	// contains filtered or unexported fields
}

Spec is a protocol specification including its name and version as well as the types of messages which are exchanged

func (*Spec) GetCode

func (s *Spec) GetCode(msg interface{}) (uint64, bool)

GetCode returns the message code of a type, and boolean second argument is false if the message type is not found

func (*Spec) Length

func (s *Spec) Length() uint64

Length returns the number of message types in the protocol

func (*Spec) NewMsg

func (s *Spec) NewMsg(code uint64) (interface{}, bool)

NewMsg construct a new message type given the code

Jump to

Keyboard shortcuts

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