common

package
v0.53.0 Latest Latest
Warning

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

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

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",
	})
)
View Source
var ErrRateLimitExceeded = errors.New("rate limit has been exceeded")

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 of how many a limit must be exceeded
	// in order to drop a peer.
	Tolerance int64
	// contains filtered or unexported fields
}

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 used for envelopes events.

type EventType

type EventType string

EventType used to define known envelope 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) 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 stores massages in 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 of 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{}

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
}

type PeerRateLimiter

type PeerRateLimiter struct {
	LimitPerSecIP     int64
	LimitPerSecPeerID int64
	// contains filtered or unexported fields
}

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 {
	LimitPerSecIP      int64
	LimitPerSecPeerID  int64
	WhitelistedIPs     []string
	WhitelistedPeerIDs []enode.ID
}

type RateLimiterHandler

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

type RateLimiterPeer

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

type RateLimits

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

RateLimits contains information about rate limit settings. It is exchanged using rateLimitingCode packet or in the handshake.

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 (left) 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
	// RateLimits returns the current rate limits for the host
	RateLimits() 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
	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