common

package
v0.77.1 Latest Latest
Warning

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

Go to latest
Published: May 12, 2021 License: MPL-2.0 Imports: 25 Imported by: 0

README

Waku Common

See here

Documentation

Index

Constants

View Source
const (
	SizeMask = byte(3) // mask used to extract the size of payload size field from the flags

	TopicLength = 4 // in bytes

	AESKeyLength = 32 // in bytes

	KeyIDSize        = 32 // in bytes
	BloomFilterSize  = 64 // in bytes
	MaxTopicInterest = 10000

	EnvelopeHeaderLength = 20

	MaxMessageSize        = uint32(10 * 1024 * 1024) // maximum accepted size of a message.
	DefaultMaxMessageSize = uint32(1024 * 1024)
	DefaultMinimumPoW     = 0.2

	ExpirationCycle   = time.Second
	TransmissionCycle = 300 * time.Millisecond

	DefaultTTL           = 50 // seconds
	DefaultSyncAllowance = 10 // seconds

	MaxLimitInSyncMailRequest = 1000

	EnvelopeTimeNotSynced uint = iota + 1
	EnvelopeOtherError

	MaxLimitInMessagesRequest = 1000
)

Waku protocol parameters

Variables

View Source
var (
	EnvelopesReceivedCounter = prom.NewCounter(prom.CounterOpts{
		Name: "waku_envelopes_received_total",
		Help: "Number of envelopes received.",
	})
	EnvelopesValidatedCounter = prom.NewCounter(prom.CounterOpts{
		Name: "waku_envelopes_validated_total",
		Help: "Number of envelopes processed successfully.",
	})
	EnvelopesRejectedCounter = prom.NewCounterVec(prom.CounterOpts{
		Name: "waku_envelopes_rejected_total",
		Help: "Number of envelopes rejected.",
	}, []string{"reason"})
	EnvelopesCacheFailedCounter = prom.NewCounterVec(prom.CounterOpts{
		Name: "waku_envelopes_cache_failures_total",
		Help: "Number of envelopes which failed to be cached.",
	}, []string{"type"})
	EnvelopesCachedCounter = prom.NewCounterVec(prom.CounterOpts{
		Name: "waku_envelopes_cached_total",
		Help: "Number of envelopes cached.",
	}, []string{"cache"})
	EnvelopesSizeMeter = prom.NewHistogram(prom.HistogramOpts{
		Name:    "waku_envelopes_size_bytes",
		Help:    "Size of processed Waku envelopes in bytes.",
		Buckets: prom.ExponentialBuckets(256, 4, 10),
	})
	RateLimitsProcessed = prom.NewCounter(prom.CounterOpts{
		Name: "waku_rate_limits_processed_total",
		Help: "Number of packets Waku rate limiter processed.",
	})
	RateLimitsExceeded = prom.NewCounterVec(prom.CounterOpts{
		Name: "waku_rate_limits_exceeded_total",
		Help: "Number of times the Waku rate limits were exceeded",
	}, []string{"type"})
	BridgeSent = prom.NewCounter(prom.CounterOpts{
		Name: "waku_bridge_sent_total",
		Help: "Number of envelopes bridged from Waku",
	})
	BridgeReceivedSucceed = prom.NewCounter(prom.CounterOpts{
		Name: "waku_bridge_received_success_total",
		Help: "Number of envelopes bridged to Waku and successfully added",
	})
	BridgeReceivedFailed = prom.NewCounter(prom.CounterOpts{
		Name: "waku_bridge_received_failure_total",
		Help: "Number of envelopes bridged to Waku and failed to be added",
	})
)

Functions

func BloomFilterMatch

func BloomFilterMatch(filter, sample []byte) bool

func BytesToUintBigEndian

func BytesToUintBigEndian(b []byte) (res uint64)

BytesToUintBigEndian converts the slice to 64-bit unsigned integer.

func BytesToUintLittleEndian

func BytesToUintLittleEndian(b []byte) (res uint64)

BytesToUintLittleEndian converts the slice to 64-bit unsigned integer.

func ContainsOnlyZeros

func ContainsOnlyZeros(data []byte) bool

ContainsOnlyZeros checks if the data contain only zeros.

func GenerateRandomID

func GenerateRandomID() (id string, err error)

GenerateRandomID generates a random string, which is then returned to be used as a key id

func GenerateSecureRandomData

func GenerateSecureRandomData(length int) ([]byte, error)

GenerateSecureRandomData generates random data where extra security is required. The purpose of this function is to prevent some bugs in software or in hardware from delivering not-very-random data. This is especially useful for AES nonce, where true randomness does not really matter, but it is very important to have a unique nonce for every message.

func IsFullNode

func IsFullNode(bloom []byte) bool

func IsMessageSigned

func IsMessageSigned(flags byte) bool

func IsPubKeyEqual

func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool

IsPubKeyEqual checks that two public keys are equal

func MakeFullNodeBloom

func MakeFullNodeBloom() []byte

func NewSentMessage

func NewSentMessage(params *MessageParams) (*sentMessage, error)

NewSentMessage creates and initializes a non-signed, non-encrypted Waku message.

func ValidateDataIntegrity

func ValidateDataIntegrity(k []byte, expectedSize int) bool

ValidateDataIntegrity returns false if the data have the wrong or contains all zeros, which is the simplest and the most common bug.

func ValidatePublicKey

func ValidatePublicKey(k *ecdsa.PublicKey) bool

ValidatePublicKey checks the format of the given public key.

Types

type DropPeerRateLimiterHandler

type DropPeerRateLimiterHandler struct {
	// Tolerance is a number by which a limit must be exceeded before a peer is dropped.
	Tolerance int64
	// contains filtered or unexported fields
}

DropPeerRateLimiterHandler implements RateLimiterHandler, represents a handler that introduces Tolerance to the number of Peer connections before Limit Exceeded errors are returned.

func (*DropPeerRateLimiterHandler) ExceedIPLimit

func (h *DropPeerRateLimiterHandler) ExceedIPLimit() error

func (*DropPeerRateLimiterHandler) ExceedPeerLimit

func (h *DropPeerRateLimiterHandler) ExceedPeerLimit() error

type Envelope

type Envelope struct {
	Expiry uint32
	TTL    uint32
	Topic  TopicType
	Data   []byte
	Nonce  uint64
	// contains filtered or unexported fields
}

Envelope represents a clear-text data packet to transmit through the Waku network. Its contents may or may not be encrypted and signed.

func NewEnvelope

func NewEnvelope(ttl uint32, topic TopicType, msg *sentMessage, now time.Time) *Envelope

NewEnvelope wraps a Waku message with expiration and destination data included into an envelope for network forwarding.

func (*Envelope) Bloom

func (e *Envelope) Bloom() []byte

Bloom maps 4-bytes Topic into 64-byte bloom filter with 3 bits set (at most).

func (*Envelope) CalculatePoW

func (e *Envelope) CalculatePoW(diff uint32)

func (*Envelope) DecodeRLP

func (e *Envelope) DecodeRLP(s *rlp.Stream) error

DecodeRLP decodes an Envelope from an RLP data stream.

func (*Envelope) Hash

func (e *Envelope) Hash() common.Hash

Hash returns the SHA3 hash of the envelope, calculating it if not yet done.

func (*Envelope) Open

func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage)

Open tries to decrypt an envelope, and populates the message fields in case of success.

func (*Envelope) OpenAsymmetric

func (e *Envelope) OpenAsymmetric(key *ecdsa.PrivateKey) (*ReceivedMessage, error)

OpenAsymmetric tries to decrypt an envelope, potentially encrypted with a particular key.

func (*Envelope) OpenSymmetric

func (e *Envelope) OpenSymmetric(key []byte) (msg *ReceivedMessage, err error)

OpenSymmetric tries to decrypt an envelope, potentially encrypted with a particular key.

func (*Envelope) PoW

func (e *Envelope) PoW() float64

PoW computes (if necessary) and returns the proof of work target of the envelope.

func (*Envelope) Seal

func (e *Envelope) Seal(options *MessageParams) error

Seal closes the envelope by spending the requested amount of time as a proof of work on hashing the data.

func (*Envelope) Size

func (e *Envelope) Size() int

Size returns the size of envelope as it is sent (i.e. public fields only)

type EnvelopeError

type EnvelopeError struct {
	Hash        common.Hash
	Code        uint
	Description string
}

EnvelopeError code and optional description of the error.

func ErrorToEnvelopeError

func ErrorToEnvelopeError(hash common.Hash, err error) EnvelopeError

ErrorToEnvelopeError converts common golang error into EnvelopeError with a code.

type EnvelopeEvent

type EnvelopeEvent struct {
	Event EventType
	Topic TopicType
	Hash  common.Hash
	Batch common.Hash
	Peer  enode.ID
	Data  interface{}
}

EnvelopeEvent represents an envelope event.

type EventType

type EventType string

EventType used to define known waku events.

const (
	// EventEnvelopeSent fires when envelope was sent to a peer.
	EventEnvelopeSent EventType = "envelope.sent"

	// EventEnvelopeExpired fires when envelop expired
	EventEnvelopeExpired EventType = "envelope.expired"

	// EventEnvelopeReceived is sent once envelope was received from a peer.
	// EventEnvelopeReceived must be sent to the feed even if envelope was previously in the cache.
	// And event, ideally, should contain information about peer that sent envelope to us.
	EventEnvelopeReceived EventType = "envelope.received"

	// EventBatchAcknowledged is sent when batch of envelopes was acknowledged by a peer.
	EventBatchAcknowledged EventType = "batch.acknowledged"

	// EventEnvelopeAvailable fires when envelop is available for filters
	EventEnvelopeAvailable EventType = "envelope.available"

	// EventMailServerRequestSent fires when such request is sent.
	EventMailServerRequestSent EventType = "mailserver.request.sent"

	// EventMailServerRequestCompleted fires after mailserver sends all the requested messages
	EventMailServerRequestCompleted EventType = "mailserver.request.completed"

	// EventMailServerRequestExpired fires after mailserver the request TTL ends.
	// This event is independent and concurrent to EventMailServerRequestCompleted.
	// Request should be considered as expired only if expiry event was received first.
	EventMailServerRequestExpired EventType = "mailserver.request.expired"

	// EventMailServerEnvelopeArchived fires after an envelope has been archived
	EventMailServerEnvelopeArchived EventType = "mailserver.envelope.archived"

	// EventMailServerSyncFinished fires when the sync of messages is finished.
	EventMailServerSyncFinished EventType = "mailserver.sync.finished"
)

type Filter

type Filter struct {
	Src        *ecdsa.PublicKey  // Sender of the message
	KeyAsym    *ecdsa.PrivateKey // Private Key of recipient
	KeySym     []byte            // Key associated with the Topic
	Topics     [][]byte          // Topics to filter messages with
	PoW        float64           // Proof of work as described in the Waku spec
	AllowP2P   bool              // Indicates whether this filter is interested in direct peer-to-peer messages
	SymKeyHash common.Hash       // The Keccak256Hash of the symmetric key, needed for optimization

	Messages MessageStore
	// contains filtered or unexported fields
}

Filter represents a Waku message filter

func (*Filter) MatchEnvelope

func (f *Filter) MatchEnvelope(envelope *Envelope) bool

MatchEnvelope checks if it's worth decrypting the message. If it returns `true`, client code is expected to attempt decrypting the message and subsequently call MatchMessage. Topics are not checked here, since this is done by topic matchers.

func (*Filter) MatchMessage

func (f *Filter) MatchMessage(msg *ReceivedMessage) bool

MatchMessage checks if the filter matches an already decrypted message (i.e. a Message that has already been handled by MatchEnvelope when checked by a previous filter). Topics are not checked here, since this is done by topic matchers.

func (*Filter) Retrieve

func (f *Filter) Retrieve() []*ReceivedMessage

Retrieve will return the list of all received messages associated to a filter.

func (*Filter) Trigger

func (f *Filter) Trigger(msg *ReceivedMessage)

Trigger adds a yet-unknown message to the filter's list of received messages.

type Filters

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

Filters represents a collection of filters

func NewFilters

func NewFilters() *Filters

NewFilters returns a newly created filter collection

func (*Filters) AllTopics added in v0.69.0

func (fs *Filters) AllTopics() []TopicType

func (*Filters) Get

func (fs *Filters) Get(id string) *Filter

Get returns a filter from the collection with a specific ID

func (*Filters) GetWatchersByTopic

func (fs *Filters) GetWatchersByTopic(topic TopicType) []*Filter

GetWatchersByTopic returns a slice containing the filters that match a specific topic

func (*Filters) Install

func (fs *Filters) Install(watcher *Filter) (string, error)

Install will add a new filter to the filter collection

func (*Filters) NotifyWatchers

func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool)

NotifyWatchers notifies any filter that has declared interest for the envelope's topic.

func (*Filters) Uninstall

func (fs *Filters) Uninstall(id string) bool

Uninstall will remove a filter whose id has been specified from the filter collection

type MemoryMessageStore

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

MemoryMessageStore represents messages stored in a memory hash table.

func NewMemoryMessageStore

func NewMemoryMessageStore() *MemoryMessageStore

NewMemoryMessageStore returns pointer to an instance of the MemoryMessageStore.

func (*MemoryMessageStore) Add

func (store *MemoryMessageStore) Add(msg *ReceivedMessage) error

Add adds message to store.

func (*MemoryMessageStore) Pop

func (store *MemoryMessageStore) Pop() ([]*ReceivedMessage, error)

Pop returns all available messages and cleans the store.

type MessageParams

type MessageParams struct {
	TTL      uint32
	Src      *ecdsa.PrivateKey
	Dst      *ecdsa.PublicKey
	KeySym   []byte
	Topic    TopicType
	WorkTime uint32
	PoW      float64
	Payload  []byte
	Padding  []byte
}

MessageParams specifies the exact way a message should be wrapped into an Envelope.

type MessageStore

type MessageStore interface {
	Add(*ReceivedMessage) error
	Pop() ([]*ReceivedMessage, error)
}

MessageStore defines interface for temporary message store.

type MessagesRequest

type MessagesRequest struct {
	// ID of the request. The current implementation requires ID to be 32-byte array,
	// however, it's not enforced for future implementation.
	ID []byte `json:"id"`

	// From is a lower bound of time range.
	From uint32 `json:"from"`

	// To is a upper bound of time range.
	To uint32 `json:"to"`

	// Limit determines the number of messages sent by the mail server
	// for the current paginated request.
	Limit uint32 `json:"limit"`

	// Cursor is used as starting point for paginated requests.
	Cursor []byte `json:"cursor"`

	// Bloom is a filter to match requested messages.
	Bloom []byte `json:"bloom"`

	// Topics is a list of topics. A returned message should
	// belong to one of the topics from the list.
	Topics [][]byte `json:"topics"`
}

MessagesRequest contains details of a request for historic messages.

func (MessagesRequest) Validate

func (r MessagesRequest) Validate() error

type MessagesResponse

type MessagesResponse struct {
	// Hash is a hash of all envelopes sent in the single batch.
	Hash common.Hash
	// Per envelope error.
	Errors []EnvelopeError
}

MessagesResponse sent as a response after processing batch of envelopes.

type MetricsRateLimiterHandler

type MetricsRateLimiterHandler struct{}

MetricsRateLimiterHandler implements RateLimiterHandler, represents a handler for reporting rate limit Exceed data to the metrics collection service (currently prometheus)

func (MetricsRateLimiterHandler) ExceedIPLimit

func (MetricsRateLimiterHandler) ExceedIPLimit() error

func (MetricsRateLimiterHandler) ExceedPeerLimit

func (MetricsRateLimiterHandler) ExceedPeerLimit() error

type Peer

type Peer interface {
	// Start performs the handshake and initialize the broadcasting of messages
	Start() error
	Stop()
	// Run start the polling loop
	Run() error

	// NotifyAboutPowRequirementChange notifies the peer that POW for the host has changed
	NotifyAboutPowRequirementChange(float64) error
	// NotifyAboutBloomFilterChange notifies the peer that bloom filter for the host has changed
	NotifyAboutBloomFilterChange([]byte) error
	// NotifyAboutTopicInterestChange notifies the peer that topics for the host have changed
	NotifyAboutTopicInterestChange([]TopicType) error

	// SetPeerTrusted sets the value of trusted, meaning we will
	// allow p2p messages from them, which is necessary to interact
	// with mailservers.
	SetPeerTrusted(bool)
	// SetRWWriter sets the socket to read/write
	SetRWWriter(p2p.MsgReadWriter)

	RequestHistoricMessages(*Envelope) error
	SendMessagesRequest(MessagesRequest) error
	SendHistoricMessageResponse([]byte) error
	SendP2PMessages([]*Envelope) error
	SendRawP2PDirect([]rlp.RawValue) error

	// Mark marks an envelope known to the peer so that it won't be sent back.
	Mark(*Envelope)
	// Marked checks if an envelope is already known to the remote peer.
	Marked(*Envelope) bool

	ID() []byte
	IP() net.IP
	EnodeID() enode.ID

	PoWRequirement() float64
	BloomFilter() []byte
	ConfirmationsEnabled() bool
}

Peer represents a remote Waku client with which the local host waku instance exchanges data / messages.

type PeerRateLimiter

type PeerRateLimiter struct {
	PacketLimitPerSecIP     int64
	PacketLimitPerSecPeerID int64

	BytesLimitPerSecIP     int64
	BytesLimitPerSecPeerID int64
	// contains filtered or unexported fields
}

PeerRateLimiter represents a rate limiter that limits communication between Peers

func NewPeerRateLimiter

func NewPeerRateLimiter(cfg *PeerRateLimiterConfig, handlers ...RateLimiterHandler) *PeerRateLimiter

func (*PeerRateLimiter) Decorate

func (r *PeerRateLimiter) Decorate(p RateLimiterPeer, rw p2p.MsgReadWriter, runLoop runLoop) error

type PeerRateLimiterConfig

type PeerRateLimiterConfig struct {
	PacketLimitPerSecIP     int64
	PacketLimitPerSecPeerID int64
	BytesLimitPerSecIP      int64
	BytesLimitPerSecPeerID  int64
	WhitelistedIPs          []string
	WhitelistedPeerIDs      []enode.ID
}

PeerRateLimiterConfig represents configurations for initialising a PeerRateLimiter

type RateLimiterHandler

type RateLimiterHandler interface {
	ExceedPeerLimit() error
	ExceedIPLimit() error
}

RateLimiterHandler interface represents handler functionality for a Rate Limiter in the cases of exceeding a peer limit and exceeding an IP limit

type RateLimiterPeer

type RateLimiterPeer interface {
	ID() []byte
	IP() net.IP
}

RateLimiterPeer interface represents a Peer that is capable of being rate limited

type RateLimits

type RateLimits struct {
	IPLimits     uint64 // amount per second from a single IP (default 0, no limits)
	PeerIDLimits uint64 // amount per second from a single peer ID (default 0, no limits)
	TopicLimits  uint64 // amount per second from a single topic (default 0, no limits)
}

RateLimits contains information about rate limit settings. It's agnostic on what it's being rate limited on (bytes or number of packets currently) It's exchanged with the status-update packet code

func (RateLimits) IsZero

func (r RateLimits) IsZero() bool

type ReceivedMessage

type ReceivedMessage struct {
	Raw []byte

	Payload   []byte
	Padding   []byte
	Signature []byte
	Salt      []byte

	PoW   float64          // Proof of work as described in the Waku spec
	Sent  uint32           // Time when the message was posted into the network
	TTL   uint32           // Maximum time to live allowed for the message
	Src   *ecdsa.PublicKey // Message recipient (identity used to decode the message)
	Dst   *ecdsa.PublicKey // Message recipient (identity used to decode the message)
	Topic TopicType

	SymKeyHash   common.Hash // The Keccak256Hash of the key
	EnvelopeHash common.Hash // Message envelope hash to act as a unique id

	P2P bool // is set to true if this message was received from mail server.
}

ReceivedMessage represents a data packet to be received through the Waku protocol and successfully decrypted.

func (*ReceivedMessage) SigToPubKey

func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey

SigToPubKey returns the public key associated to the message's signature.

func (*ReceivedMessage) ValidateAndParse

func (msg *ReceivedMessage) ValidateAndParse() bool

ValidateAndParse checks the message validity and extracts the fields in case of success.

type TimeSyncError

type TimeSyncError error

TimeSyncError error for clock skew errors.

type TopicType

type TopicType [TopicLength]byte

TopicType represents a cryptographically secure, probabilistic partial classifications of a message, determined as the first (leftmost) 4 bytes of the SHA3 hash of some arbitrary data given by the original author of the message.

func BytesToTopic

func BytesToTopic(b []byte) (t TopicType)

BytesToTopic converts from the byte array representation of a topic into the TopicType type.

func (TopicType) MarshalText

func (t TopicType) MarshalText() ([]byte, error)

MarshalText returns the hex representation of t.

func (*TopicType) String

func (t *TopicType) String() string

String converts a topic byte array to a string representation.

func (TopicType) ToBloom

func (t TopicType) ToBloom() []byte

ToBloom converts the topic (4 bytes) to the bloom filter (64 bytes)

func (*TopicType) UnmarshalText

func (t *TopicType) UnmarshalText(input []byte) error

UnmarshalText parses a hex representation to a topic.

type WakuHost

type WakuHost interface {
	// HandlePeer handles the connection of a new peer
	HandlePeer(Peer, p2p.MsgReadWriter) error
	// MaxMessageSize returns the maximum accepted message size.
	MaxMessageSize() uint32
	// LightClientMode returns whether the host is running in light client mode
	LightClientMode() bool
	// Mailserver returns whether the host is running a mailserver
	Mailserver() bool
	// LightClientModeConnectionRestricted indicates that connection to light client in light client mode not allowed
	LightClientModeConnectionRestricted() bool
	// ConfirmationsEnabled returns true if message confirmations are enabled.
	ConfirmationsEnabled() bool
	// PacketRateLimits returns the current rate limits for the host
	PacketRateLimits() RateLimits
	// BytesRateLimits returns the current rate limits for the host
	BytesRateLimits() RateLimits
	// MinPow returns the MinPow for the host
	MinPow() float64
	// BloomFilterMode returns whether the host is using bloom filter
	BloomFilterMode() bool
	// BloomFilter returns the bloom filter for the host
	BloomFilter() []byte
	//TopicInterest returns the topics for the host
	TopicInterest() []TopicType
	// IsEnvelopeCached checks if envelope with specific hash has already been received and cached.
	IsEnvelopeCached(common.Hash) bool
	// Envelopes returns all the envelopes queued
	Envelopes() []*Envelope
	SendEnvelopeEvent(EnvelopeEvent) int
	// OnNewEnvelopes handles newly received envelopes from a peer
	OnNewEnvelopes([]*Envelope, Peer) ([]EnvelopeError, error)
	// OnNewP2PEnvelopes handles envelopes received though the P2P
	// protocol (i.e from a mailserver in most cases)
	OnNewP2PEnvelopes([]*Envelope) error
	// OnMessagesResponse handles when the peer receive a message response
	// from a mailserver
	OnMessagesResponse(MessagesResponse, Peer) error
	// OnMessagesRequest handles when the peer receive a message request
	// this only works if the peer is a mailserver
	OnMessagesRequest(MessagesRequest, Peer) error
	// OnDeprecatedMessagesRequest handles when the peer receive a message request
	// using the *Envelope format. Currently the only production client (status-react)
	// is exclusively using this one.
	OnDeprecatedMessagesRequest(*Envelope, Peer) error

	OnBatchAcknowledged(common.Hash, Peer) error
	OnP2PRequestCompleted([]byte, Peer) error
}

WakuHost is the local instance of waku, which both interacts with remote clients (peers) and local clients (through RPC API)

Jump to

Keyboard shortcuts

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