Use directly the Whisper types instead of distinct strings, we test for string in fromJson anyhow

This commit is contained in:
kdeme 2019-04-23 14:45:37 +02:00
parent 1df3c7202b
commit ce523550c0
5 changed files with 106 additions and 122 deletions

View File

@ -36,14 +36,9 @@ type
HexDataStr* = distinct string HexDataStr* = distinct string
EthAddressStr* = distinct string # Same as HexDataStr but must be less <= 20 bytes EthAddressStr* = distinct string # Same as HexDataStr but must be less <= 20 bytes
EthHashStr* = distinct string # Same as HexDataStr but must be exactly 32 bytes EthHashStr* = distinct string # Same as HexDataStr but must be exactly 32 bytes
IdentifierStr* = distinct string # 32 bytes, no 0x prefix! Identifier* = distinct string # 32 bytes, no 0x prefix!
PublicKeyStr* = distinct string # 0x prefix + 65 bytes
PrivateKeyStr* = distinct string # 0x prefix + 32 bytes
SymKeyStr* = distinct string # 0x prefix + 32 bytes
TopicStr* = distinct string # 0x prefix + 4 bytes
HexStrings = HexQuantityStr | HexDataStr | EthAddressStr | EthHashStr | HexStrings = HexQuantityStr | HexDataStr | EthAddressStr | EthHashStr |
IdentifierStr | PublicKeyStr | PrivateKeyStr | SymKeyStr | Identifier
TopicStr
template len*(value: HexStrings): int = value.string.len template len*(value: HexStrings): int = value.string.len
@ -136,11 +131,6 @@ const
SInvalidData = "Invalid hex data format for Ethereum" SInvalidData = "Invalid hex data format for Ethereum"
SInvalidAddress = "Invalid address format for Ethereum" SInvalidAddress = "Invalid address format for Ethereum"
SInvalidHash = "Invalid hash format for Ethereum" SInvalidHash = "Invalid hash format for Ethereum"
SInvalidIdentifier = "Invalid format for identifier"
SInvalidPublicKey = "Invalid format for public key"
SInvalidPrivateKey = "Invalid format for private key"
SInvalidSymKey = "Invalid format for symmetric key"
SInvalidTopic = "Invalid format for topic"
proc validateHexQuantity*(value: string) {.inline.} = proc validateHexQuantity*(value: string) {.inline.} =
if unlikely(not value.isValidHexQuantity): if unlikely(not value.isValidHexQuantity):
@ -217,6 +207,21 @@ proc `%`*(value: whisper_protocol.Topic): JsonNode =
proc `%`*(value: Bytes): JsonNode = proc `%`*(value: Bytes): JsonNode =
result = %("0x" & value.toHex) result = %("0x" & value.toHex)
# Helpers for the fromJson procs
proc toPublicKey*(key: string): PublicKey {.inline.} =
result = initPublicKey(key[4 .. ^1])
proc toPrivateKey*(key: string): PrivateKey {.inline.} =
result = initPrivateKey(key[2 .. ^1])
proc toSymKey*(key: string): SymKey {.inline.} =
hexToByteArray(key[2 .. ^1], result)
proc toTopic*(topic: string): whisper_protocol.Topic {.inline.} =
hexToByteArray(topic[2 .. ^1], result)
# Marshalling from JSON to Nim types that includes format checking # Marshalling from JSON to Nim types that includes format checking
func invalidMsg(name: string): string = "When marshalling from JSON, parameter \"" & name & "\" is not valid" func invalidMsg(name: string): string = "When marshalling from JSON, parameter \"" & name & "\" is not valid"
@ -249,12 +254,12 @@ proc fromJson*(n: JsonNode, argName: string, result: var EthHashStr) =
raise newException(ValueError, invalidMsg(argName) & " as an Ethereum hash \"" & hexStr & "\"") raise newException(ValueError, invalidMsg(argName) & " as an Ethereum hash \"" & hexStr & "\"")
result = hexStr.EthHashStr result = hexStr.EthHashStr
proc fromJson*(n: JsonNode, argName: string, result: var IdentifierStr) = proc fromJson*(n: JsonNode, argName: string, result: var Identifier) =
n.kind.expect(JString, argName) n.kind.expect(JString, argName)
let hexStr = n.getStr() let hexStr = n.getStr()
if not hexStr.isValidIdentifier: if not hexStr.isValidIdentifier:
raise newException(ValueError, invalidMsg(argName) & " as a identifier \"" & hexStr & "\"") raise newException(ValueError, invalidMsg(argName) & " as a identifier \"" & hexStr & "\"")
result = hexStr.IdentifierStr result = hexStr.Identifier
proc fromJson*(n: JsonNode, argName: string, result: var UInt256) = proc fromJson*(n: JsonNode, argName: string, result: var UInt256) =
n.kind.expect(JString, argName) n.kind.expect(JString, argName)
@ -263,44 +268,37 @@ proc fromJson*(n: JsonNode, argName: string, result: var UInt256) =
raise newException(ValueError, invalidMsg(argName) & " as a UInt256 \"" & hexStr & "\"") raise newException(ValueError, invalidMsg(argName) & " as a UInt256 \"" & hexStr & "\"")
result = readUintBE[256](hexToPaddedByteArray[32](hexStr)) result = readUintBE[256](hexToPaddedByteArray[32](hexStr))
proc fromJson*(n: JsonNode, argName: string, result: var PublicKeyStr) = proc fromJson*(n: JsonNode, argName: string, result: var PublicKey) =
n.kind.expect(JString, argName) n.kind.expect(JString, argName)
let hexStr = n.getStr() let hexStr = n.getStr()
if not hexStr.isValidPublicKey: if not hexStr.isValidPublicKey:
raise newException(ValueError, invalidMsg(argName) & " as a public key \"" & hexStr & "\"") raise newException(ValueError, invalidMsg(argName) & " as a public key \"" & hexStr & "\"")
result = hexStr.PublicKeyStr result = hexStr.toPublicKey
proc fromJson*(n: JsonNode, argName: string, result: var PrivateKeyStr) = proc fromJson*(n: JsonNode, argName: string, result: var PrivateKey) =
n.kind.expect(JString, argName) n.kind.expect(JString, argName)
let hexStr = n.getStr() let hexStr = n.getStr()
if not hexStr.isValidPrivateKey: if not hexStr.isValidPrivateKey:
raise newException(ValueError, invalidMsg(argName) & " as a private key \"" & hexStr & "\"") raise newException(ValueError, invalidMsg(argName) & " as a private key \"" & hexStr & "\"")
result = hexStr.PrivateKeyStr result = hexStr.toPrivateKey
proc fromJson*(n: JsonNode, argName: string, result: var SymKeyStr) = proc fromJson*(n: JsonNode, argName: string, result: var SymKey) =
n.kind.expect(JString, argName) n.kind.expect(JString, argName)
let hexStr = n.getStr() let hexStr = n.getStr()
if not hexStr.isValidSymKey: if not hexStr.isValidSymKey:
raise newException(ValueError, invalidMsg(argName) & " as a symmetric key \"" & hexStr & "\"") raise newException(ValueError, invalidMsg(argName) & " as a symmetric key \"" & hexStr & "\"")
result = hexStr.SymKeyStr result = toSymKey(hexStr)
proc fromJson*(n: JsonNode, argName: string, result: var TopicStr) =
n.kind.expect(JString, argName)
let hexStr = n.getStr()
if not hexStr.isValidTopic:
raise newException(ValueError, invalidMsg(argName) & " as a topic \"" & hexStr & "\"")
result = hexStr.TopicStr
# Following procs currently required only for testing, the `createRpcSigs` macro
# requires it as it will convert the JSON results back to the original Nim
# types, but it needs the `fromJson` calls for those specific Nim types to do so
proc fromJson*(n: JsonNode, argName: string, result: var whisper_protocol.Topic) = proc fromJson*(n: JsonNode, argName: string, result: var whisper_protocol.Topic) =
n.kind.expect(JString, argName) n.kind.expect(JString, argName)
let hexStr = n.getStr() let hexStr = n.getStr()
if not hexStr.isValidTopic: if not hexStr.isValidTopic:
raise newException(ValueError, invalidMsg(argName) & " as a topic \"" & hexStr & "\"") raise newException(ValueError, invalidMsg(argName) & " as a topic \"" & hexStr & "\"")
hexToByteArray(hexStr.string[2 .. ^1], result) result = toTopic(hexStr)
# Following procs currently required only for testing, the `createRpcSigs` macro
# requires it as it will convert the JSON results back to the original Nim
# types, but it needs the `fromJson` calls for those specific Nim types to do so
proc fromJson*(n: JsonNode, argName: string, result: var Bytes) = proc fromJson*(n: JsonNode, argName: string, result: var Bytes) =
n.kind.expect(JString, argName) n.kind.expect(JString, argName)
let hexStr = n.getStr() let hexStr = n.getStr()
@ -314,10 +312,3 @@ proc fromJson*(n: JsonNode, argName: string, result: var Hash256) =
if not hexStr.isValidHash256: if not hexStr.isValidHash256:
raise newException(ValueError, invalidMsg(argName) & " as a Hash256 \"" & hexStr & "\"") raise newException(ValueError, invalidMsg(argName) & " as a Hash256 \"" & hexStr & "\"")
hexToByteArray(hexStr.string, result.data) hexToByteArray(hexStr.string, result.data)
proc fromJson*(n: JsonNode, argName: string, result: var PublicKey) =
n.kind.expect(JString, argName)
let hexStr = n.getStr()
if not hexStr.isValidPublicKey:
raise newException(ValueError, invalidMsg(argName) & " as a public key \"" & hexStr & "\"")
result = initPublicKey(hexStr.string[4 .. ^1])

View File

@ -132,11 +132,11 @@ type
WhisperFilterOptions* = object WhisperFilterOptions* = object
# Parameter from user # Parameter from user
symKeyID*: Option[IdentifierStr] # ID of symmetric key for message decryption. symKeyID*: Option[Identifier] # ID of symmetric key for message decryption.
privateKeyID*: Option[IdentifierStr] # ID of private (asymmetric) key for message decryption. privateKeyID*: Option[Identifier] # ID of private (asymmetric) key for message decryption.
sig*: Option[PublicKeyStr] # (Optional) Public key of the signature. sig*: Option[PublicKey] # (Optional) Public key of the signature.
minPow*: Option[float64] # (Optional) Minimal PoW requirement for incoming messages. minPow*: Option[float64] # (Optional) Minimal PoW requirement for incoming messages.
topics*: Option[seq[TopicStr]] # (Optional when asym key): Array of possible topics (or partial topics). topics*: Option[seq[whisper_protocol.Topic]] # (Optional when asym key): Array of possible topics (or partial topics).
allowP2P*: Option[bool] # (Optional) Indicates if this filter allows processing of direct peer-to-peer messages. allowP2P*: Option[bool] # (Optional) Indicates if this filter allows processing of direct peer-to-peer messages.
WhisperFilterMessage* = object WhisperFilterMessage* = object
@ -153,11 +153,11 @@ type
WhisperPostMessage* = object WhisperPostMessage* = object
# Parameter from user # Parameter from user
symKeyID*: Option[IdentifierStr] # ID of symmetric key for message encryption. symKeyID*: Option[Identifier] # ID of symmetric key for message encryption.
pubKey*: Option[PublicKeyStr] # Public key for message encryption. pubKey*: Option[PublicKey] # Public key for message encryption.
sig*: Option[IdentifierStr] # (Optional) ID of the signing key. sig*: Option[Identifier] # (Optional) ID of the signing key.
ttl*: uint64 # Time-to-live in seconds. ttl*: uint64 # Time-to-live in seconds.
topic*: Option[TopicStr] # Message topic (mandatory when key is symmetric). topic*: Option[whisper_protocol.Topic] # Message topic (mandatory when key is symmetric).
payload*: HexDataStr # Payload to be encrypted. payload*: HexDataStr # Payload to be encrypted.
padding*: Option[HexDataStr] # (Optional) Padding (byte array of arbitrary length). padding*: Option[HexDataStr] # (Optional) Padding (byte array of arbitrary length).
powTime*: float64 # Maximal time in seconds to be spent on proof of work. powTime*: float64 # Maximal time in seconds to be spent on proof of work.

View File

@ -71,28 +71,26 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
let peerNode = newNode(enode) let peerNode = newNode(enode)
result = node.setPeerTrusted(peerNode.id) result = node.setPeerTrusted(peerNode.id)
rpcsrv.rpc("shh_newKeyPair") do() -> IdentifierStr: rpcsrv.rpc("shh_newKeyPair") do() -> Identifier:
## Generates a new public and private key pair for message decryption and ## Generates a new public and private key pair for message decryption and
## encryption. ## encryption.
## ##
## Returns key identifier on success and an error on failure. ## Returns key identifier on success and an error on failure.
result = generateRandomID().IdentifierStr result = generateRandomID().Identifier
keys.asymKeys.add(result.string, newKeyPair()) keys.asymKeys.add(result.string, newKeyPair())
rpcsrv.rpc("shh_addPrivateKey") do(key: PrivateKeyStr) -> IdentifierStr: rpcsrv.rpc("shh_addPrivateKey") do(key: PrivateKey) -> Identifier:
## Stores the key pair, and returns its ID. ## Stores the key pair, and returns its ID.
## ##
## key: Private key as hex bytes. ## key: Private key as hex bytes.
## ##
## Returns key identifier on success and an error on failure. ## Returns key identifier on success and an error on failure.
result = generateRandomID().IdentifierStr result = generateRandomID().Identifier
# No need to check if 0x prefix as the JSON Marshalling should handle this keys.asymKeys.add(result.string, KeyPair(seckey: key,
var privkey = initPrivateKey(key.string[2 .. ^1]) pubkey: key.getPublicKey()))
keys.asymKeys.add(result.string, KeyPair(seckey: privkey,
pubkey: privkey.getPublicKey()))
rpcsrv.rpc("shh_deleteKeyPair") do(id: IdentifierStr) -> bool: rpcsrv.rpc("shh_deleteKeyPair") do(id: Identifier) -> bool:
## Deletes the specifies key if it exists. ## Deletes the specifies key if it exists.
## ##
## id: Identifier of key pair ## id: Identifier of key pair
@ -101,7 +99,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
var unneeded: KeyPair var unneeded: KeyPair
result = keys.asymKeys.take(id.string, unneeded) result = keys.asymKeys.take(id.string, unneeded)
rpcsrv.rpc("shh_hasKeyPair") do(id: IdentifierStr) -> bool: rpcsrv.rpc("shh_hasKeyPair") do(id: Identifier) -> bool:
## Checks if the whisper node has a private key of a key pair matching the ## Checks if the whisper node has a private key of a key pair matching the
## given ID. ## given ID.
## ##
@ -110,7 +108,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
## Returns true on success and an error on failure. ## Returns true on success and an error on failure.
result = keys.asymkeys.hasKey(id.string) result = keys.asymkeys.hasKey(id.string)
rpcsrv.rpc("shh_getPublicKey") do(id: IdentifierStr) -> PublicKey: rpcsrv.rpc("shh_getPublicKey") do(id: Identifier) -> PublicKey:
## Returns the public key for identity ID. ## Returns the public key for identity ID.
## ##
## id: Identifier of key pair ## id: Identifier of key pair
@ -119,7 +117,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
# Note: key not found exception as error in case not existing # Note: key not found exception as error in case not existing
result = keys.asymkeys[id.string].pubkey result = keys.asymkeys[id.string].pubkey
rpcsrv.rpc("shh_getPrivateKey") do(id: IdentifierStr) -> PrivateKey: rpcsrv.rpc("shh_getPrivateKey") do(id: Identifier) -> PrivateKey:
## Returns the private key for identity ID. ## Returns the private key for identity ID.
## ##
## id: Identifier of key pair ## id: Identifier of key pair
@ -128,13 +126,13 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
# Note: key not found exception as error in case not existing # Note: key not found exception as error in case not existing
result = keys.asymkeys[id.string].seckey result = keys.asymkeys[id.string].seckey
rpcsrv.rpc("shh_newSymKey") do() -> IdentifierStr: rpcsrv.rpc("shh_newSymKey") do() -> Identifier:
## Generates a random symmetric key and stores it under an ID, which is then ## Generates a random symmetric key and stores it under an ID, which is then
## returned. Can be used encrypting and decrypting messages where the key is ## returned. Can be used encrypting and decrypting messages where the key is
## known to both parties. ## known to both parties.
## ##
## Returns key identifier on success and an error on failure. ## Returns key identifier on success and an error on failure.
result = generateRandomID().IdentifierStr result = generateRandomID().Identifier
var key: SymKey var key: SymKey
if randomBytes(key) != key.len: if randomBytes(key) != key.len:
error "Generation of SymKey failed" error "Generation of SymKey failed"
@ -142,20 +140,17 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
keys.symKeys.add(result.string, key) keys.symKeys.add(result.string, key)
rpcsrv.rpc("shh_addSymKey") do(key: SymKeyStr) -> IdentifierStr: rpcsrv.rpc("shh_addSymKey") do(key: SymKey) -> Identifier:
## Stores the key, and returns its ID. ## Stores the key, and returns its ID.
## ##
## key: The raw key for symmetric encryption as hex bytes. ## key: The raw key for symmetric encryption as hex bytes.
## ##
## Returns key identifier on success and an error on failure. ## Returns key identifier on success and an error on failure.
result = generateRandomID().IdentifierStr result = generateRandomID().Identifier
var symKey: SymKey keys.symKeys.add(result.string, key)
# No need to check if 0x prefix as the JSON Marshalling should handle this
hexToByteArray(key.string[2 .. ^1], symKey)
keys.symKeys.add(result.string, symKey)
rpcsrv.rpc("shh_generateSymKeyFromPassword") do(password: string) -> IdentifierStr: rpcsrv.rpc("shh_generateSymKeyFromPassword") do(password: string) -> Identifier:
## Generates the key from password, stores it, and returns its ID. ## Generates the key from password, stores it, and returns its ID.
## ##
## password: Password. ## password: Password.
@ -169,10 +164,10 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
if pbkdf2(ctx, password, "", 65356, symKey) != sizeof(SymKey): if pbkdf2(ctx, password, "", 65356, symKey) != sizeof(SymKey):
raise newException(ValueError, "Failed generating key") raise newException(ValueError, "Failed generating key")
result = generateRandomID().IdentifierStr result = generateRandomID().Identifier
keys.symKeys.add(result.string, symKey) keys.symKeys.add(result.string, symKey)
rpcsrv.rpc("shh_hasSymKey") do(id: IdentifierStr) -> bool: rpcsrv.rpc("shh_hasSymKey") do(id: Identifier) -> bool:
## Returns true if there is a key associated with the name string. ## Returns true if there is a key associated with the name string.
## Otherwise, returns false. ## Otherwise, returns false.
## ##
@ -181,7 +176,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
## Returns (true or false) on success and an error on failure. ## Returns (true or false) on success and an error on failure.
result = keys.symkeys.hasKey(id.string) result = keys.symkeys.hasKey(id.string)
rpcsrv.rpc("shh_getSymKey") do(id: IdentifierStr) -> SymKey: rpcsrv.rpc("shh_getSymKey") do(id: Identifier) -> SymKey:
## Returns the symmetric key associated with the given ID. ## Returns the symmetric key associated with the given ID.
## ##
## id: Identifier of key. ## id: Identifier of key.
@ -190,7 +185,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
# Note: key not found exception as error in case not existing # Note: key not found exception as error in case not existing
result = keys.symkeys[id.string] result = keys.symkeys[id.string]
rpcsrv.rpc("shh_deleteSymKey") do(id: IdentifierStr) -> bool: rpcsrv.rpc("shh_deleteSymKey") do(id: Identifier) -> bool:
## Deletes the key associated with the name string if it exists. ## Deletes the key associated with the name string if it exists.
## ##
## id: Identifier of key. ## id: Identifier of key.
@ -200,7 +195,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
result = keys.symKeys.take(id.string, unneeded) result = keys.symKeys.take(id.string, unneeded)
rpcsrv.rpc("shh_subscribe") do(id: string, rpcsrv.rpc("shh_subscribe") do(id: string,
options: WhisperFilterOptions) -> IdentifierStr: options: WhisperFilterOptions) -> Identifier:
## Creates and registers a new subscription to receive notifications for ## Creates and registers a new subscription to receive notifications for
## inbound whisper messages. Returns the ID of the newly created ## inbound whisper messages. Returns the ID of the newly created
## subscription. ## subscription.
@ -214,7 +209,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
# TODO: implement subscriptions, only for WS & IPC? # TODO: implement subscriptions, only for WS & IPC?
discard discard
rpcsrv.rpc("shh_unsubscribe") do(id: IdentifierStr) -> bool: rpcsrv.rpc("shh_unsubscribe") do(id: Identifier) -> bool:
## Cancels and removes an existing subscription. ## Cancels and removes an existing subscription.
## ##
## id: Subscription identifier ## id: Subscription identifier
@ -229,7 +224,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
if asym.isNone() and topic.isNone(): if asym.isNone() and topic.isNone():
raise newException(ValueError, "Topic mandatory with symmetric key") raise newException(ValueError, "Topic mandatory with symmetric key")
rpcsrv.rpc("shh_newMessageFilter") do(options: WhisperFilterOptions) -> IdentifierStr: rpcsrv.rpc("shh_newMessageFilter") do(options: WhisperFilterOptions) -> Identifier:
## Create a new filter within the node. This filter can be used to poll for ## Create a new filter within the node. This filter can be used to poll for
## new messages that match the set of criteria. ## new messages that match the set of criteria.
## ##
@ -248,24 +243,20 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
if options.symKeyID.isSome(): if options.symKeyID.isSome():
filter.symKey= some(keys.symKeys[options.symKeyID.get().string]) filter.symKey= some(keys.symKeys[options.symKeyID.get().string])
if options.sig.isSome(): filter.src = options.sig
# Need to strip 0x04
filter.src = some(initPublicKey(options.sig.get().string[4 .. ^1]))
if options.minPow.isSome(): if options.minPow.isSome():
filter.powReq = options.minPow.get() filter.powReq = options.minPow.get()
if options.topics.isSome(): if options.topics.isSome():
filter.topics = map(options.topics.get(), filter.topics = options.topics.get()
proc(x: TopicStr): whisper_protocol.Topic =
hexToByteArray(x.string[2 .. ^1], result))
if options.allowP2P.isSome(): if options.allowP2P.isSome():
filter.allowP2P = options.allowP2P.get() filter.allowP2P = options.allowP2P.get()
result = node.subscribeFilter(filter).IdentifierStr result = node.subscribeFilter(filter).Identifier
rpcsrv.rpc("shh_deleteMessageFilter") do(id: IdentifierStr) -> bool: rpcsrv.rpc("shh_deleteMessageFilter") do(id: Identifier) -> bool:
## Uninstall a message filter in the node. ## Uninstall a message filter in the node.
## ##
## id: Filter identifier as returned when the filter was created. ## id: Filter identifier as returned when the filter was created.
@ -273,7 +264,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
## Returns true on success, error on failure. ## Returns true on success, error on failure.
result = node.unsubscribeFilter(id.string) result = node.unsubscribeFilter(id.string)
rpcsrv.rpc("shh_getFilterMessages") do(id: IdentifierStr) -> seq[WhisperFilterMessage]: rpcsrv.rpc("shh_getFilterMessages") do(id: Identifier) -> seq[WhisperFilterMessage]:
## Retrieve messages that match the filter criteria and are received between ## Retrieve messages that match the filter criteria and are received between
## the last time this function was called and now. ## the last time this function was called and now.
## ##
@ -320,8 +311,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
padding: Option[Bytes] padding: Option[Bytes]
targetPeer: Option[NodeId] targetPeer: Option[NodeId]
if message.pubKey.isSome(): pubKey = message.pubKey
pubKey = some(initPublicKey(message.pubKey.get().string[4 .. ^1]))
if message.sig.isSome(): if message.sig.isSome():
sigPrivKey = some(keys.asymKeys[message.sig.get().string].seckey) sigPrivKey = some(keys.asymKeys[message.sig.get().string].seckey)
@ -331,7 +321,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: WhisperKeys, rpcsrv: RpcServer)
# Note: If no topic it will be defaulted to 0x00000000 # Note: If no topic it will be defaulted to 0x00000000
if message.topic.isSome(): if message.topic.isSome():
hexToByteArray(message.topic.get().string[2 .. ^1], topic) topic = message.topic.get()
if message.padding.isSome(): if message.padding.isSome():
padding = some(hexToSeqByte(message.padding.get().string)) padding = some(hexToSeqByte(message.padding.get().string))

View File

@ -82,21 +82,21 @@ proc shh_setMaxMessageSize(size: uint64): bool
proc shh_setMinPoW(pow: float): bool proc shh_setMinPoW(pow: float): bool
proc shh_markTrustedPeer(enode: string): bool proc shh_markTrustedPeer(enode: string): bool
proc shh_newKeyPair(): IdentifierStr proc shh_newKeyPair(): Identifier
proc shh_addPrivateKey(key: string): IdentifierStr proc shh_addPrivateKey(key: string): Identifier
proc shh_deleteKeyPair(id: IdentifierStr): bool proc shh_deleteKeyPair(id: Identifier): bool
proc shh_hasKeyPair(id: IdentifierStr): bool proc shh_hasKeyPair(id: Identifier): bool
proc shh_getPublicKey(id: IdentifierStr): PublicKeyStr proc shh_getPublicKey(id: Identifier): PublicKey
proc shh_getPrivateKey(id: IdentifierStr): PrivateKeyStr proc shh_getPrivateKey(id: Identifier): PrivateKey
proc shh_newSymKey(): IdentifierStr proc shh_newSymKey(): Identifier
proc shh_addSymKey(key: string): IdentifierStr proc shh_addSymKey(key: string): Identifier
proc shh_generateSymKeyFromPassword(password: string): IdentifierStr proc shh_generateSymKeyFromPassword(password: string): Identifier
proc shh_hasSymKey(id: IdentifierStr): bool proc shh_hasSymKey(id: Identifier): bool
proc shh_getSymKey(id: IdentifierStr): SymKeyStr proc shh_getSymKey(id: Identifier): SymKey
proc shh_deleteSymKey(id: IdentifierStr): bool proc shh_deleteSymKey(id: Identifier): bool
proc shh_newMessageFilter(options: WhisperFilterOptions): IdentifierStr proc shh_newMessageFilter(options: WhisperFilterOptions): Identifier
proc shh_deleteMessageFilter(id: IdentifierStr): bool proc shh_deleteMessageFilter(id: Identifier): bool
proc shh_getFilterMessages(id: IdentifierStr): seq[WhisperFilterMessage] proc shh_getFilterMessages(id: Identifier): seq[WhisperFilterMessage]
proc shh_post(message: WhisperPostMessage): bool proc shh_post(message: WhisperPostMessage): bool

View File

@ -77,8 +77,8 @@ proc doTests =
let pubkey = "0x04e5fd642a0f630bbb1e4cd7df629d7b8b019457a9a74f983c0484a045cebb176def86a54185b50bbba6bbf97779173695e92835d63109c23471e6da382f922fdb" let pubkey = "0x04e5fd642a0f630bbb1e4cd7df629d7b8b019457a9a74f983c0484a045cebb176def86a54185b50bbba6bbf97779173695e92835d63109c23471e6da382f922fdb"
let keyID2 = waitFor client.shh_addPrivateKey(privkey) let keyID2 = waitFor client.shh_addPrivateKey(privkey)
check: check:
waitFor(client.shh_getPublicKey(keyID2)).string == pubkey waitFor(client.shh_getPublicKey(keyID2)) == pubkey.toPublicKey
waitFor(client.shh_getPrivateKey(keyID2)).string == privkey waitFor(client.shh_getPrivateKey(keyID2)) == privkey.toPrivateKey
waitFor(client.shh_hasKeyPair(keyID2)) == true waitFor(client.shh_hasKeyPair(keyID2)) == true
waitFor(client.shh_deleteKeyPair(keyID2)) == true waitFor(client.shh_deleteKeyPair(keyID2)) == true
waitFor(client.shh_hasKeyPair(keyID2)) == false waitFor(client.shh_hasKeyPair(keyID2)) == false
@ -94,7 +94,7 @@ proc doTests =
let symKey = "0x0000000000000000000000000000000000000000000000000000000000000001" let symKey = "0x0000000000000000000000000000000000000000000000000000000000000001"
let keyID2 = waitFor client.shh_addSymKey(symKey) let keyID2 = waitFor client.shh_addSymKey(symKey)
check: check:
waitFor(client.shh_getSymKey(keyID2)).string == symKey waitFor(client.shh_getSymKey(keyID2)) == symKey.toSymKey
waitFor(client.shh_hasSymKey(keyID2)) == true waitFor(client.shh_hasSymKey(keyID2)) == true
waitFor(client.shh_deleteSymKey(keyID2)) == true waitFor(client.shh_deleteSymKey(keyID2)) == true
waitFor(client.shh_hasSymKey(keyID2)) == false waitFor(client.shh_hasSymKey(keyID2)) == false
@ -104,10 +104,10 @@ proc doTests =
let keyID4 = waitFor client.shh_generateSymKeyFromPassword("password") let keyID4 = waitFor client.shh_generateSymKeyFromPassword("password")
let keyID5 = waitFor client.shh_generateSymKeyFromPassword("nimbus!") let keyID5 = waitFor client.shh_generateSymKeyFromPassword("nimbus!")
check: check:
waitFor(client.shh_getSymKey(keyID3)).string == waitFor(client.shh_getSymKey(keyID3)) ==
waitFor(client.shh_getSymKey(keyID4)).string waitFor(client.shh_getSymKey(keyID4))
waitFor(client.shh_getSymKey(keyID3)).string != waitFor(client.shh_getSymKey(keyID3)) !=
waitFor(client.shh_getSymKey(keyID5)).string waitFor(client.shh_getSymKey(keyID5))
waitFor(client.shh_hasSymKey(keyID3)) == true waitFor(client.shh_hasSymKey(keyID3)) == true
waitFor(client.shh_deleteSymKey(keyID3)) == true waitFor(client.shh_deleteSymKey(keyID3)) == true
waitFor(client.shh_hasSymKey(keyID3)) == false waitFor(client.shh_hasSymKey(keyID3)) == false
@ -116,7 +116,7 @@ proc doTests =
# Some defaults for the filter & post tests # Some defaults for the filter & post tests
let let
ttl = 30'u64 ttl = 30'u64
topic = "0x12345678" topicStr = "0x12345678"
payload = "0x45879632" payload = "0x45879632"
# A very low target and long time so we are sure the test never fails # A very low target and long time so we are sure the test never fails
# because of this # because of this
@ -125,13 +125,14 @@ proc doTests =
test "shh symKey post and filter loop": test "shh symKey post and filter loop":
let let
topic = topicStr.toTopic()
symKeyID = waitFor client.shh_newSymKey() symKeyID = waitFor client.shh_newSymKey()
options = WhisperFilterOptions(symKeyID: some(symKeyID), options = WhisperFilterOptions(symKeyID: some(symKeyID),
topics: some(@[topic.TopicStr])) topics: some(@[topic]))
filterID = waitFor client.shh_newMessageFilter(options) filterID = waitFor client.shh_newMessageFilter(options)
message = WhisperPostMessage(symKeyID: some(symKeyID), message = WhisperPostMessage(symKeyID: some(symKeyID),
ttl: ttl, ttl: ttl,
topic: some(topic.TopicStr), topic: some(topic),
payload: payload.HexDataStr, payload: payload.HexDataStr,
powTime: powTime, powTime: powTime,
powTarget: powTarget) powTarget: powTarget)
@ -145,20 +146,21 @@ proc doTests =
messages[0].sig.isNone() messages[0].sig.isNone()
messages[0].recipientPublicKey.isNone() messages[0].recipientPublicKey.isNone()
messages[0].ttl == ttl messages[0].ttl == ttl
("0x" & messages[0].topic.toHex) == topic messages[0].topic == topic
("0x" & messages[0].payload.toHex) == payload messages[0].payload == hexToSeqByte(payload)
messages[0].padding.len > 0 messages[0].padding.len > 0
messages[0].pow >= powTarget messages[0].pow >= powTarget
test "shh asymKey post and filter loop": test "shh asymKey post and filter loop":
let let
topic = topicStr.toTopic()
privateKeyID = waitFor client.shh_newKeyPair() privateKeyID = waitFor client.shh_newKeyPair()
options = WhisperFilterOptions(privateKeyID: some(privateKeyID)) options = WhisperFilterOptions(privateKeyID: some(privateKeyID))
filterID = waitFor client.shh_newMessageFilter(options) filterID = waitFor client.shh_newMessageFilter(options)
pubKey = waitFor client.shh_getPublicKey(privateKeyID) pubKey = waitFor client.shh_getPublicKey(privateKeyID)
message = WhisperPostMessage(pubKey: some(pubKey), message = WhisperPostMessage(pubKey: some(pubKey),
ttl: ttl, ttl: ttl,
topic: some(topic.TopicStr), topic: some(topic),
payload: payload.HexDataStr, payload: payload.HexDataStr,
powTime: powTime, powTime: powTime,
powTarget: powTarget) powTarget: powTarget)
@ -170,26 +172,27 @@ proc doTests =
check: check:
messages.len == 1 messages.len == 1
messages[0].sig.isNone() messages[0].sig.isNone()
("0x04" & $messages[0].recipientPublicKey.get()) == pubKey.string messages[0].recipientPublicKey.get() == pubKey
messages[0].ttl == ttl messages[0].ttl == ttl
("0x" & messages[0].topic.toHex) == topic messages[0].topic == topic
("0x" & messages[0].payload.toHex) == payload messages[0].payload == hexToSeqByte(payload)
messages[0].padding.len > 0 messages[0].padding.len > 0
messages[0].pow >= powTarget messages[0].pow >= powTarget
test "shh signature in post and filter loop": test "shh signature in post and filter loop":
let let
topic = topicStr.toTopic()
symKeyID = waitFor client.shh_newSymKey() symKeyID = waitFor client.shh_newSymKey()
privateKeyID = waitFor client.shh_newKeyPair() privateKeyID = waitFor client.shh_newKeyPair()
pubKey = waitFor client.shh_getPublicKey(privateKeyID) pubKey = waitFor client.shh_getPublicKey(privateKeyID)
options = WhisperFilterOptions(symKeyID: some(symKeyID), options = WhisperFilterOptions(symKeyID: some(symKeyID),
topics: some(@[topic.TopicStr]), topics: some(@[topic]),
sig: some(pubKey)) sig: some(pubKey))
filterID = waitFor client.shh_newMessageFilter(options) filterID = waitFor client.shh_newMessageFilter(options)
message = WhisperPostMessage(symKeyID: some(symKeyID), message = WhisperPostMessage(symKeyID: some(symKeyID),
sig: some(privateKeyID), sig: some(privateKeyID),
ttl: ttl, ttl: ttl,
topic: some(topic.TopicStr), topic: some(topic),
payload: payload.HexDataStr, payload: payload.HexDataStr,
powTime: powTime, powTime: powTime,
powTarget: powTarget) powTarget: powTarget)
@ -200,11 +203,11 @@ proc doTests =
let messages = waitFor client.shh_getFilterMessages(filterID) let messages = waitFor client.shh_getFilterMessages(filterID)
check: check:
messages.len == 1 messages.len == 1
("0x04" & $messages[0].sig.get()) == pubKey.string messages[0].sig.get() == pubKey
messages[0].recipientPublicKey.isNone() messages[0].recipientPublicKey.isNone()
messages[0].ttl == ttl messages[0].ttl == ttl
("0x" & messages[0].topic.toHex) == topic messages[0].topic == topic
("0x" & messages[0].payload.toHex) == payload messages[0].payload == hexToSeqByte(payload)
messages[0].padding.len > 0 messages[0].padding.len > 0
messages[0].pow >= powTarget messages[0].pow >= powTarget