From c64a370fe7a49d8d8d287d043870ecec1251676e Mon Sep 17 00:00:00 2001 From: kdeme Date: Thu, 3 Oct 2019 15:42:35 +0200 Subject: [PATCH] Whisper documentation updates --- eth/p2p/rlpx_protocols/whisper_protocol.nim | 98 +++++++++++++++------ 1 file changed, 70 insertions(+), 28 deletions(-) diff --git a/eth/p2p/rlpx_protocols/whisper_protocol.nim b/eth/p2p/rlpx_protocols/whisper_protocol.nim index 845eee6..c19925d 100644 --- a/eth/p2p/rlpx_protocols/whisper_protocol.nim +++ b/eth/p2p/rlpx_protocols/whisper_protocol.nim @@ -1,10 +1,36 @@ +# +# Whisper +# (c) Copyright 2018-2019 +# Status Research & Development GmbH +# +# Licensed under either of +# Apache License, version 2.0, (LICENSE-APACHEv2) +# MIT license (LICENSE-MIT) +# + ## Whisper +## ******* ## ## Whisper is a gossip protocol that synchronizes a set of messages across nodes ## with attention given to sender and recipient anonymitiy. Messages are ## categorized by a topic and stay alive in the network based on a time-to-live ## measured in seconds. Spam prevention is based on proof-of-work, where large ## or long-lived messages must spend more work. +## +## Example usage +## ---------- +## First an `EthereumNode` needs to be created, either with all capabilities set +## or with specifically the Whisper capability set. +## The latter can be done like this: +## +## .. code-block::nim +## var node = newEthereumNode(keypair, address, netId, nil, +## addAllCapabilities = false) +## node.addCapability Whisper +## +## Now calls such as ``postMessage`` and ``subscribeFilter`` can be done. +## However, they only make real sense after ``connectToNetwork`` was started. As +## else there will be no peers to send and receive messages from. import algorithm, bitops, math, options, sequtils, strutils, tables, times, chronos, @@ -25,24 +51,29 @@ const bloomSize = 512 div 8 defaultQueueCapacity = 256 defaultFilterQueueCapacity = 64 - whisperVersion* = 6 - whisperVersionStr* = $whisperVersion - defaultMinPow* = 0.2'f64 - defaultMaxMsgSize* = 1024'u32 * 1024'u32 # * 10 # should be no higher than max RLPx size - messageInterval* = chronos.milliseconds(300) ## Interval at which messages are send to peers, in ms - pruneInterval* = chronos.milliseconds(1000) ## Interval at which message queue is pruned, in ms + whisperVersion* = 6 ## Whisper version. + whisperVersionStr* = $whisperVersion ## Whisper version. + defaultMinPow* = 0.2'f64 ## The default minimum PoW requirement for this node. + defaultMaxMsgSize* = 1024'u32 * 1024'u32 ## The current default and max + ## message size. This can never be larger than the maximum RLPx message size. + messageInterval* = chronos.milliseconds(300) ## Interval at which messages are + ## send to peers, in ms. + pruneInterval* = chronos.milliseconds(1000) ## Interval at which message + ## queue is pruned, in ms. type Hash* = MDigest[256] - SymKey* = array[256 div 8, byte] ## AES256 key - Topic* = array[4, byte] - Bloom* = array[bloomSize, byte] ## XXX: nim-eth-bloom has really quirky API and fixed - ## bloom size. - ## stint is massive overkill / poor fit - a bloom filter is an array of bits, - ## not a number + SymKey* = array[256 div 8, byte] ## AES256 key. + Topic* = array[4, byte] ## 4 bytes that can be used to filter messages on. + Bloom* = array[bloomSize, byte] ## A bloom filter that can be used to identify + ## a number of topics that a peer is interested in. + # XXX: nim-eth-bloom has really quirky API and fixed + # bloom size. + # stint is massive overkill / poor fit - a bloom filter is an array of bits, + # not a number Payload* = object - ## Payload is what goes in the data field of the Envelope + ## Payload is what goes in the data field of the Envelope. src*: Option[PrivateKey] ## Optional key used for signing message dst*: Option[PublicKey] ## Optional key used for asymmetric encryption @@ -51,6 +82,8 @@ type padding*: Option[Bytes] ## Padding - if unset, will automatically pad up to ## nearest maxPadLen-byte boundary DecodedPayload* = object + ## The decoded payload of a received message. + src*: Option[PublicKey] ## If the message was signed, this is the public key ## of the source payload*: Bytes ## Application data / message contents @@ -59,7 +92,7 @@ type Envelope* = object ## What goes on the wire in the whisper protocol - a payload and some ## book-keeping - ## Don't touch field order, there's lots of macro magic that depends on it + # Don't touch field order, there's lots of macro magic that depends on it expiry*: uint32 ## Unix timestamp when message expires ttl*: uint32 ## Time-to-live, seconds - message was created at (expiry - ttl) topic*: Topic @@ -77,6 +110,8 @@ type isP2P: bool ReceivedMessage* = object + ## A received message that matched a filter and was possible to decrypt. + ## Contains the decoded payload and additional information. decoded*: DecodedPayload timestamp*: uint32 ttl*: uint32 @@ -115,7 +150,7 @@ type powReq*: float64 allowP2P*: bool - bloom: Bloom # cached bloom filter of all topics of filter + bloom: Bloom # Cached bloom filter of all topics of filter handler: FilterMsgHandler queue: seq[ReceivedMessage] @@ -185,6 +220,7 @@ proc bloomFilterMatch(filter, sample: Bloom): bool = return true proc fullBloom*(): Bloom = + ## Returns a fully set bloom filter. To be used when allowing all topics. # There is no setMem exported in system, assume compiler is smart enough? for i in 0.. defaultMaxMsgSize: warn "size > defaultMaxMsgSize" return false @@ -1034,25 +1073,28 @@ proc setMaxMessageSize*(node: EthereumNode, size: uint32): bool = return true proc setPeerTrusted*(node: EthereumNode, peerId: NodeId): bool = - ## Set a connected peer as trusted + ## Set a connected peer as trusted. for peer in node.peers(Whisper): if peer.remote.id == peerId: peer.state(Whisper).trusted = true return true proc setLightNode*(node: EthereumNode, isLightNode: bool) = - ## Set this node as a Whisper light node + ## Set this node as a Whisper light node. + ## ## NOTE: Should be run before connection is made with peers as this - ## setting is only communicated at peer handshake + ## setting is only communicated at peer handshake. node.protocolState(Whisper).config.isLightNode = isLightNode proc configureWhisper*(node: EthereumNode, config: WhisperConfig) = - ## Apply a Whisper configuration + ## Apply a Whisper configuration. + ## ## NOTE: Should be run before connection is made with peers as some - ## of the settings are only communicated at peer handshake + ## of the settings are only communicated at peer handshake. node.protocolState(Whisper).config = config proc resetMessageQueue*(node: EthereumNode) = - ## Full reset of the message queue - ## NOTE: Not something that should be run in normal circumstances + ## Full reset of the message queue. + ## + ## NOTE: Not something that should be run in normal circumstances. node.protocolState(Whisper).queue = initQueue(defaultQueueCapacity)