Add access to set/get the message padding + tests
This commit is contained in:
parent
4f53236233
commit
3d2abbdfdd
|
@ -48,7 +48,7 @@ type
|
||||||
src*: Option[PublicKey] ## If the message was signed, this is the public key
|
src*: Option[PublicKey] ## If the message was signed, this is the public key
|
||||||
## of the source
|
## of the source
|
||||||
payload*: Bytes ## Application data / message contents
|
payload*: Bytes ## Application data / message contents
|
||||||
padding*: Option[Bytes] # XXX: to be added still
|
padding*: Option[Bytes] ## Message padding
|
||||||
|
|
||||||
Envelope* = object
|
Envelope* = object
|
||||||
## What goes on the wire in the whisper protocol - a payload and some
|
## What goes on the wire in the whisper protocol - a payload and some
|
||||||
|
@ -268,6 +268,7 @@ proc encode*(self: Payload): Option[Bytes] =
|
||||||
|
|
||||||
let padLen =
|
let padLen =
|
||||||
if self.padding.isSome(): self.padding.get().len
|
if self.padding.isSome(): self.padding.get().len
|
||||||
|
# is there a reason why 256 bytes are padded when the dataLen is 256?
|
||||||
else: padMaxLen - (dataLen mod padMaxLen)
|
else: padMaxLen - (dataLen mod padMaxLen)
|
||||||
|
|
||||||
# buffer space that we need to allocate
|
# buffer space that we need to allocate
|
||||||
|
@ -397,6 +398,13 @@ proc decode*(data: openarray[byte], dst = none[PrivateKey](),
|
||||||
return
|
return
|
||||||
res.src = some(key)
|
res.src = some(key)
|
||||||
|
|
||||||
|
if hasSignature:
|
||||||
|
if plain.len > pos + eth_keys.RawSignatureSize:
|
||||||
|
res.padding = some(plain[pos .. ^(eth_keys.RawSignatureSize+1)])
|
||||||
|
else:
|
||||||
|
if plain.len > pos:
|
||||||
|
res.padding = some(plain[pos .. ^1])
|
||||||
|
|
||||||
return some(res)
|
return some(res)
|
||||||
|
|
||||||
# Envelopes --------------------------------------------------------------------
|
# Envelopes --------------------------------------------------------------------
|
||||||
|
@ -829,14 +837,14 @@ proc sendMessage*(node: EthereumNode, env: var Envelope): bool =
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
# XXX: add padding
|
|
||||||
proc postMessage*(node: EthereumNode, pubKey = none[PublicKey](),
|
proc postMessage*(node: EthereumNode, pubKey = none[PublicKey](),
|
||||||
symKey = none[SymKey](), src = none[PrivateKey](),
|
symKey = none[SymKey](), src = none[PrivateKey](),
|
||||||
ttl: uint32, topic: Topic, payload: Bytes, powTime = 1,
|
ttl: uint32, topic: Topic, payload: Bytes,
|
||||||
|
padding = none[Bytes](), powTime = 1,
|
||||||
targetPeer = none[NodeId]()): bool =
|
targetPeer = none[NodeId]()): bool =
|
||||||
# NOTE: Allow a post without a key? Encryption is mandatory in v6?
|
# NOTE: Allow a post without a key? Encryption is mandatory in v6?
|
||||||
var payload = encode(Payload(payload: payload, src: src, dst: pubKey,
|
var payload = encode(Payload(payload: payload, src: src, dst: pubKey,
|
||||||
symKey: symKey))
|
symKey: symKey, padding: padding))
|
||||||
if payload.isSome():
|
if payload.isSome():
|
||||||
var env = Envelope(expiry:epochTime().uint32 + ttl + powTime.uint32,
|
var env = Envelope(expiry:epochTime().uint32 + ttl + powTime.uint32,
|
||||||
ttl: ttl, topic: topic, data: payload.get(), nonce: 0)
|
ttl: ttl, topic: topic, data: payload.get(), nonce: 0)
|
||||||
|
|
|
@ -123,6 +123,8 @@ let encPublicKey = encPrivateKey.getPublicKey()
|
||||||
let signPrivateKey = initPrivateKey("365bda0757d22212b04fada4b9222f8c3da59b49398fa04cf612481cd893b0a3")
|
let signPrivateKey = initPrivateKey("365bda0757d22212b04fada4b9222f8c3da59b49398fa04cf612481cd893b0a3")
|
||||||
let signPublicKey = signPrivateKey.getPublicKey()
|
let signPublicKey = signPrivateKey.getPublicKey()
|
||||||
var symKey: SymKey
|
var symKey: SymKey
|
||||||
|
# To test with geth: all 0's key is invalid in geth console
|
||||||
|
symKey[31] = 1
|
||||||
let topic = [byte 0x12, 0, 0, 0]
|
let topic = [byte 0x12, 0, 0, 0]
|
||||||
|
|
||||||
if config.main:
|
if config.main:
|
||||||
|
|
156
tests/tshh.nim
156
tests/tshh.nim
|
@ -19,8 +19,10 @@ suite "Whisper payload":
|
||||||
let encoded = shh.encode(payload)
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
let decoded = shh.decode(encoded.get())
|
let decoded = shh.decode(encoded.get())
|
||||||
doAssert decoded.isSome()
|
check:
|
||||||
doAssert payload.payload == decoded.get().payload
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
decoded.get().padding.get().len == 251 # 256 -1 -1 -3
|
||||||
|
|
||||||
test "should roundtrip with symmetric encryption":
|
test "should roundtrip with symmetric encryption":
|
||||||
var symKey: SymKey
|
var symKey: SymKey
|
||||||
|
@ -28,8 +30,10 @@ suite "Whisper payload":
|
||||||
let encoded = shh.encode(payload)
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
let decoded = shh.decode(encoded.get(), symKey = some(symKey))
|
let decoded = shh.decode(encoded.get(), symKey = some(symKey))
|
||||||
doAssert decoded.isSome()
|
check:
|
||||||
doAssert payload.payload == decoded.get().payload
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
decoded.get().padding.get().len == 251 # 256 -1 -1 -3
|
||||||
|
|
||||||
test "should roundtrip with signature":
|
test "should roundtrip with signature":
|
||||||
let privKey = eth_keys.newPrivateKey()
|
let privKey = eth_keys.newPrivateKey()
|
||||||
|
@ -38,9 +42,11 @@ suite "Whisper payload":
|
||||||
let encoded = shh.encode(payload)
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
let decoded = shh.decode(encoded.get())
|
let decoded = shh.decode(encoded.get())
|
||||||
doAssert decoded.isSome()
|
check:
|
||||||
doAssert payload.payload == decoded.get().payload
|
decoded.isSome()
|
||||||
doAssert privKey.getPublicKey() == decoded.get().src.get()
|
payload.payload == decoded.get().payload
|
||||||
|
privKey.getPublicKey() == decoded.get().src.get()
|
||||||
|
decoded.get().padding.get().len == 186 # 256 -1 -1 -3 -65
|
||||||
|
|
||||||
test "should roundtrip with asymmetric encryption":
|
test "should roundtrip with asymmetric encryption":
|
||||||
let privKey = eth_keys.newPrivateKey()
|
let privKey = eth_keys.newPrivateKey()
|
||||||
|
@ -50,17 +56,122 @@ suite "Whisper payload":
|
||||||
let encoded = shh.encode(payload)
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
let decoded = shh.decode(encoded.get(), dst = some(privKey))
|
let decoded = shh.decode(encoded.get(), dst = some(privKey))
|
||||||
doAssert decoded.isSome()
|
check:
|
||||||
doAssert payload.payload == decoded.get().payload
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
decoded.get().padding.get().len == 251 # 256 -1 -1 -3
|
||||||
|
|
||||||
test "should roundtrip with asymmetric encryption":
|
test "should return specified bloom":
|
||||||
# Geth test: https://github.com/ethersphere/go-ethereum/blob/d3441ebb563439bac0837d70591f92e2c6080303/whisper/whisperv6/whisper_test.go#L834
|
# Geth test: https://github.com/ethersphere/go-ethereum/blob/d3441ebb563439bac0837d70591f92e2c6080303/whisper/whisperv6/whisper_test.go#L834
|
||||||
let top0 = [byte 0, 0, 255, 6]
|
let top0 = [byte 0, 0, 255, 6]
|
||||||
var x: Bloom
|
var x: Bloom
|
||||||
x[0] = byte 1
|
x[0] = byte 1
|
||||||
x[32] = byte 1
|
x[32] = byte 1
|
||||||
x[^1] = byte 128
|
x[^1] = byte 128
|
||||||
doAssert @(top0.topicBloom) == @x
|
check @(top0.topicBloom) == @x
|
||||||
|
|
||||||
|
suite "Whisper payload padding":
|
||||||
|
test "should do max padding":
|
||||||
|
let payload = Payload(payload: repeat(byte 1, 254))
|
||||||
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
|
let decoded = shh.decode(encoded.get())
|
||||||
|
check:
|
||||||
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
decoded.get().padding.isSome()
|
||||||
|
decoded.get().padding.get().len == 256 # as dataLen == 256
|
||||||
|
|
||||||
|
test "should do max padding with signature":
|
||||||
|
let privKey = eth_keys.newPrivateKey()
|
||||||
|
|
||||||
|
let payload = Payload(src: some(privKey), payload: repeat(byte 1, 189))
|
||||||
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
|
let decoded = shh.decode(encoded.get())
|
||||||
|
check:
|
||||||
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
privKey.getPublicKey() == decoded.get().src.get()
|
||||||
|
decoded.get().padding.isSome()
|
||||||
|
decoded.get().padding.get().len == 256 # as dataLen == 256
|
||||||
|
|
||||||
|
test "should do min padding":
|
||||||
|
let payload = Payload(payload: repeat(byte 1, 253))
|
||||||
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
|
let decoded = shh.decode(encoded.get())
|
||||||
|
check:
|
||||||
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
decoded.get().padding.isSome()
|
||||||
|
decoded.get().padding.get().len == 1 # as dataLen == 255
|
||||||
|
|
||||||
|
test "should do min padding with signature":
|
||||||
|
let privKey = eth_keys.newPrivateKey()
|
||||||
|
|
||||||
|
let payload = Payload(src: some(privKey), payload: repeat(byte 1, 188))
|
||||||
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
|
let decoded = shh.decode(encoded.get())
|
||||||
|
check:
|
||||||
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
privKey.getPublicKey() == decoded.get().src.get()
|
||||||
|
decoded.get().padding.isSome()
|
||||||
|
decoded.get().padding.get().len == 1 # as dataLen == 255
|
||||||
|
|
||||||
|
test "should roundtrip custom padding":
|
||||||
|
let payload = Payload(payload: repeat(byte 1, 10),
|
||||||
|
padding: some(repeat(byte 2, 100)))
|
||||||
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
|
let decoded = shh.decode(encoded.get())
|
||||||
|
check:
|
||||||
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
decoded.get().padding.isSome()
|
||||||
|
payload.padding.get() == decoded.get().padding.get()
|
||||||
|
|
||||||
|
test "should roundtrip custom 0 padding":
|
||||||
|
let padding: seq[byte] = @[]
|
||||||
|
let payload = Payload(payload: repeat(byte 1, 10),
|
||||||
|
padding: some(padding))
|
||||||
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
|
let decoded = shh.decode(encoded.get())
|
||||||
|
check:
|
||||||
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
decoded.get().padding.isNone()
|
||||||
|
|
||||||
|
test "should roundtrip custom padding with signature":
|
||||||
|
let privKey = eth_keys.newPrivateKey()
|
||||||
|
let payload = Payload(src: some(privKey), payload: repeat(byte 1, 10),
|
||||||
|
padding: some(repeat(byte 2, 100)))
|
||||||
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
|
let decoded = shh.decode(encoded.get())
|
||||||
|
check:
|
||||||
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
privKey.getPublicKey() == decoded.get().src.get()
|
||||||
|
decoded.get().padding.isSome()
|
||||||
|
payload.padding.get() == decoded.get().padding.get()
|
||||||
|
|
||||||
|
test "should roundtrip custom 0 padding with signature":
|
||||||
|
let padding: seq[byte] = @[]
|
||||||
|
let privKey = eth_keys.newPrivateKey()
|
||||||
|
let payload = Payload(src: some(privKey), payload: repeat(byte 1, 10),
|
||||||
|
padding: some(padding))
|
||||||
|
let encoded = shh.encode(payload)
|
||||||
|
|
||||||
|
let decoded = shh.decode(encoded.get())
|
||||||
|
check:
|
||||||
|
decoded.isSome()
|
||||||
|
payload.payload == decoded.get().payload
|
||||||
|
privKey.getPublicKey() == decoded.get().src.get()
|
||||||
|
decoded.get().padding.isNone()
|
||||||
|
|
||||||
# example from https://github.com/paritytech/parity-ethereum/blob/93e1040d07e385d1219d00af71c46c720b0a1acf/whisper/src/message.rs#L439
|
# example from https://github.com/paritytech/parity-ethereum/blob/93e1040d07e385d1219d00af71c46c720b0a1acf/whisper/src/message.rs#L439
|
||||||
let
|
let
|
||||||
|
@ -76,7 +187,7 @@ suite "Whisper envelope":
|
||||||
# XXX checked with parity, should check with geth too - found a potential bug
|
# XXX checked with parity, should check with geth too - found a potential bug
|
||||||
# in parity while playing with it:
|
# in parity while playing with it:
|
||||||
# https://github.com/paritytech/parity-ethereum/issues/9625
|
# https://github.com/paritytech/parity-ethereum/issues/9625
|
||||||
doAssert $calcPowHash(env0) ==
|
check $calcPowHash(env0) ==
|
||||||
"A13B48480AEB3123CD2358516E2E8EE9FCB0F4CB37E68CD09FDF7F9A7E14767C"
|
"A13B48480AEB3123CD2358516E2E8EE9FCB0F4CB37E68CD09FDF7F9A7E14767C"
|
||||||
|
|
||||||
suite "Whisper queue":
|
suite "Whisper queue":
|
||||||
|
@ -86,22 +197,23 @@ suite "Whisper queue":
|
||||||
let msg0 = initMessage(env0)
|
let msg0 = initMessage(env0)
|
||||||
let msg1 = initMessage(env1)
|
let msg1 = initMessage(env1)
|
||||||
|
|
||||||
queue.add(msg0)
|
discard queue.add(msg0)
|
||||||
queue.add(msg1)
|
discard queue.add(msg1)
|
||||||
|
|
||||||
doAssert queue.items.len() == 1
|
check:
|
||||||
|
queue.items.len() == 1
|
||||||
doAssert queue.items[0].env.nonce ==
|
queue.items[0].env.nonce ==
|
||||||
(if msg0.pow > msg1.pow: msg0.env.nonce else: msg1.env.nonce)
|
(if msg0.pow > msg1.pow: msg0.env.nonce else: msg1.env.nonce)
|
||||||
|
|
||||||
test "should not throw out messages as long as there is capacity":
|
test "should not throw out messages as long as there is capacity":
|
||||||
var queue = initQueue(2)
|
var queue = initQueue(2)
|
||||||
|
|
||||||
queue.add(initMessage(env0))
|
check:
|
||||||
queue.add(initMessage(env1))
|
queue.add(initMessage(env0)) == true
|
||||||
|
queue.add(initMessage(env1)) == true
|
||||||
|
|
||||||
doAssert queue.items.len() == 2
|
queue.items.len() == 2
|
||||||
|
|
||||||
test "check field order against expected rlp order":
|
test "check field order against expected rlp order":
|
||||||
doAssert rlp.encode(env0) ==
|
check rlp.encode(env0) ==
|
||||||
rlp.encodeList(env0.expiry, env0.ttl, env0.topic, env0.data, env0.nonce)
|
rlp.encodeList(env0.expiry, env0.ttl, env0.topic, env0.data, env0.nonce)
|
||||||
|
|
Loading…
Reference in New Issue