protocols

package
v2.5.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Mar 3, 2020 License: GPL-3.0 Imports: 15 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 assigments 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   = Payer(true)
	Receiver = Payer(false)
)
View Source
const (
	ErrMsgTooLong = iota
	ErrDecode
	ErrWrite
	ErrInvalidMsgCode
	ErrInvalidMsgType
	ErrHandshake
	ErrNoHandler
	ErrHandler
)

error codes used by this protocol scheme

Variables

This section is empty.

Functions

This section is empty.

Types

type Accounting

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

Accounting implements the Hook interface It interfaces to the balances through the Balance interface, while interfacing with protocols and its prices through the Prices interface

func NewAccounting

func NewAccounting(balance Balance, po Prices) *Accounting

func (*Accounting) Receive

func (ah *Accounting) Receive(peer *Peer, size uint32, msg interface{}) error

Implement Hook.Receive Receive takes a peer, a size and a msg and - calculates the cost for the local node receiving a msg of size from peer using the Prices interface - credits/debits local node using balance interface

func (*Accounting) Send

func (ah *Accounting) Send(peer *Peer, size uint32, msg interface{}) error

Implement Hook.Send Send takes a peer, a size and a msg and - calculates the cost for the local node sending a msg of size to peer using the Prices interface - credits/debits local node using balance interface

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
}

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

type Error

type Error struct {
	Code int
	// contains filtered or unexported fields
}

Error implements the standard go error interface. Use:

errorf(code, format, params ...interface{})

Prints as:

<description>: <details>

where description is given by code in errorToString and details is fmt.Sprintf(format, params...)

exported field Code can be checked

func (Error) Error

func (e Error) Error() (message string)

type Hook

type Hook interface {
	//A hook for sending messages
	Send(peer *Peer, size uint32, msg interface{}) error
	//A hook for receiving messages
	Receive(peer *Peer, size uint32, msg interface{}) 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 Payer

type Payer bool

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(p *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(err error)

Drop disconnects a peer. TODO: may need to implement protocol drop only? don't want to kick off the peer if they are useful for other protocols

func (*Peer) Handshake

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

Handshake negotiates a handshake on the peer connection * arguments

  • context
  • the local handshake to be sent to the remote peer
  • funcion 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) Run

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

Run starts the forever loop that handles incoming messages called within the p2p.Protocol#Run function 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

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

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: `Send` will pass a `Sender` payer, `Receive` will pass the `Receiver` argument. Thus: If Sending and sender pays, amount positive, otherwise negative If Receiving, and receiver pays, amount positive, otherwise negative

type Prices

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

Prices defines how prices are being passed on to the accounting instance

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
	// 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

type WrappedMsg

type WrappedMsg struct {
	Context []byte
	Size    uint32
	Payload []byte
}

WrappedMsg is used to propagate marshalled context alongside message payloads

Jump to

Keyboard shortcuts

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