Fix & add Whisper RPC tests + add isValidHexData with length check

This commit is contained in:
kdeme 2019-04-08 17:55:50 +02:00
parent 65908d5359
commit 1df3c7202b
2 changed files with 133 additions and 36 deletions

View File

@ -93,6 +93,9 @@ func isValidHexData*(value: string, header = true): bool =
return false
return true
template isValidHexData(value: string, hexLen: int, header = true): bool =
value.len == hexLen and value.isValidHexData(header)
func isValidEthAddress*(value: string): bool =
# 20 bytes for EthAddress plus "0x"
# Addresses are allowed to be shorter than 20 bytes for convenience
@ -102,27 +105,31 @@ func isValidEthHash*(value: string): bool =
# 32 bytes for EthAddress plus "0x"
# Currently hashes are required to be exact lengths
# TODO: Allow shorter hashes (pad with zeros) for convenience?
result = value.len == 66 and value.isValidHexData
result = value.isValidHexData(66)
func isValidIdentifier*(value: string): bool =
# 32 bytes for Whisper ID, no 0x prefix
result = value.len == 64 and value.isvalidHexData(header = false)
result = value.isValidHexData(64, false)
func isValidPublicKey*(value: string): bool =
# 65 bytes for Public Key plus 1 byte for 0x prefix
result = value.len == 132 and value.isValidHexData
result = value.isValidHexData(132)
func isValidPrivateKey*(value: string): bool =
# 32 bytes for Private Key plus 1 byte for 0x prefix
result = value.len == 66 and value.isValidHexData
result = value.isValidHexData(66)
func isValidSymKey*(value: string): bool =
# 32 bytes for Private Key plus 1 byte for 0x prefix
result = value.len == 66 and value.isValidHexData
result = value.isValidHexData(66)
func isValidHash256*(value: string): bool =
# 32 bytes for Hash256 plus 1 byte for 0x prefix
result = value.isValidHexData(66)
func isValidTopic*(value: string): bool =
# 4 bytes for Topic plus 1 byte for 0x prefix
result = value.len == 10 and value.isValidHexData
result = value.isValidHexData(10)
const
SInvalidQuantity = "Invalid hex quantity format for Ethereum"
@ -283,3 +290,34 @@ proc fromJson*(n: JsonNode, argName: string, result: var TopicStr) =
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) =
n.kind.expect(JString, argName)
let hexStr = n.getStr()
if not hexStr.isValidTopic:
raise newException(ValueError, invalidMsg(argName) & " as a topic \"" & hexStr & "\"")
hexToByteArray(hexStr.string[2 .. ^1], result)
proc fromJson*(n: JsonNode, argName: string, result: var Bytes) =
n.kind.expect(JString, argName)
let hexStr = n.getStr()
if not hexStr.isValidHexData:
raise newException(ValueError, invalidMsg(argName) & " as a hex data \"" & hexStr & "\"")
result = hexToSeqByte(hexStr.string)
proc fromJson*(n: JsonNode, argName: string, result: var Hash256) =
n.kind.expect(JString, argName)
let hexStr = n.getStr()
if not hexStr.isValidHash256:
raise newException(ValueError, invalidMsg(argName) & " as a Hash256 \"" & hexStr & "\"")
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

@ -1,5 +1,5 @@
import
unittest, strformat, options, json_rpc/[rpcserver, rpcclient],
unittest, strformat, options, byteutils, json_rpc/[rpcserver, rpcclient],
eth/common as eth_common, eth/p2p as eth_p2p,
eth/[rlp, keys], eth/p2p/rlpx_protocols/whisper_protocol,
../nimbus/rpc/[common, hexstrings, rpc_types, whisper], ../nimbus/config
@ -113,41 +113,100 @@ proc doTests =
waitFor(client.shh_hasSymKey(keyID3)) == false
waitFor(client.shh_deleteSymKey(keyID3)) == false
test "shh symKey post and filter":
var options: WhisperFilterOptions
options.symKeyID = some(waitFor client.shh_newSymKey())
options.topics = some(@["0x12345678".TopicStr])
let filterID = waitFor client.shh_newMessageFilter(options)
# Some defaults for the filter & post tests
let
ttl = 30'u64
topic = "0x12345678"
payload = "0x45879632"
# A very low target and long time so we are sure the test never fails
# because of this
powTarget = 0.001
powTime = 1.0
var message: WhisperPostMessage
message.symKeyID = options.symKeyID
message.ttl = 30
message.topic = some("0x12345678".TopicStr)
message.payload = "0x45879632".HexDataStr
message.powTime = 1.0
message.powTarget = 0.001
test "shh symKey post and filter loop":
let
symKeyID = waitFor client.shh_newSymKey()
options = WhisperFilterOptions(symKeyID: some(symKeyID),
topics: some(@[topic.TopicStr]))
filterID = waitFor client.shh_newMessageFilter(options)
message = WhisperPostMessage(symKeyID: some(symKeyID),
ttl: ttl,
topic: some(topic.TopicStr),
payload: payload.HexDataStr,
powTime: powTime,
powTarget: powTarget)
check:
waitFor(client.shh_setMinPoW(powTarget)) == true
waitFor(client.shh_post(message)) == true
# TODO: this does not work due to overloads?
# var messages = waitFor client.shh_getFilterMessages(filterID)
test "shh asymKey post and filter":
var options: WhisperFilterOptions
let keyID = waitFor client.shh_newKeyPair()
options.privateKeyID = some(keyID)
let filterID = waitFor client.shh_newMessageFilter(options)
var message: WhisperPostMessage
message.pubKey = some(waitFor(client.shh_getPublicKey(keyID)))
message.ttl = 30
message.topic = some("0x12345678".TopicStr)
message.payload = "0x45879632".HexDataStr
message.powTime = 1.0
message.powTarget = 0.001
let messages = waitFor client.shh_getFilterMessages(filterID)
check:
messages.len == 1
messages[0].sig.isNone()
messages[0].recipientPublicKey.isNone()
messages[0].ttl == ttl
("0x" & messages[0].topic.toHex) == topic
("0x" & messages[0].payload.toHex) == payload
messages[0].padding.len > 0
messages[0].pow >= powTarget
test "shh asymKey post and filter loop":
let
privateKeyID = waitFor client.shh_newKeyPair()
options = WhisperFilterOptions(privateKeyID: some(privateKeyID))
filterID = waitFor client.shh_newMessageFilter(options)
pubKey = waitFor client.shh_getPublicKey(privateKeyID)
message = WhisperPostMessage(pubKey: some(pubKey),
ttl: ttl,
topic: some(topic.TopicStr),
payload: payload.HexDataStr,
powTime: powTime,
powTarget: powTarget)
check:
waitFor(client.shh_setMinPoW(powTarget)) == true
waitFor(client.shh_post(message)) == true
# TODO: this does not work due to overloads?
# var messages = waitFor client.shh_getFilterMessages(filterID)
let messages = waitFor client.shh_getFilterMessages(filterID)
check:
messages.len == 1
messages[0].sig.isNone()
("0x04" & $messages[0].recipientPublicKey.get()) == pubKey.string
messages[0].ttl == ttl
("0x" & messages[0].topic.toHex) == topic
("0x" & messages[0].payload.toHex) == payload
messages[0].padding.len > 0
messages[0].pow >= powTarget
test "shh signature in post and filter loop":
let
symKeyID = waitFor client.shh_newSymKey()
privateKeyID = waitFor client.shh_newKeyPair()
pubKey = waitFor client.shh_getPublicKey(privateKeyID)
options = WhisperFilterOptions(symKeyID: some(symKeyID),
topics: some(@[topic.TopicStr]),
sig: some(pubKey))
filterID = waitFor client.shh_newMessageFilter(options)
message = WhisperPostMessage(symKeyID: some(symKeyID),
sig: some(privateKeyID),
ttl: ttl,
topic: some(topic.TopicStr),
payload: payload.HexDataStr,
powTime: powTime,
powTarget: powTarget)
check:
waitFor(client.shh_setMinPoW(powTarget)) == true
waitFor(client.shh_post(message)) == true
let messages = waitFor client.shh_getFilterMessages(filterID)
check:
messages.len == 1
("0x04" & $messages[0].sig.get()) == pubKey.string
messages[0].recipientPublicKey.isNone()
messages[0].ttl == ttl
("0x" & messages[0].topic.toHex) == topic
("0x" & messages[0].payload.toHex) == payload
messages[0].padding.len > 0
messages[0].pow >= powTarget
rpcServer.stop()
rpcServer.close()