mirror of https://github.com/status-im/nim-eth.git
Allow for discv4 chronos strict usage
And group p2p tests that can be run with strict usage along the way.
This commit is contained in:
parent
0f3bb61678
commit
9fed10de88
|
@ -49,13 +49,11 @@ task test_discv4, "Run discovery v4 tests":
|
||||||
task test_p2p, "Run p2p tests":
|
task test_p2p, "Run p2p tests":
|
||||||
test_discv5_task()
|
test_discv5_task()
|
||||||
|
|
||||||
|
runTest("tests/p2p/all_tests")
|
||||||
|
|
||||||
|
# Code that still requires chronosStrict = false
|
||||||
for filename in [
|
for filename in [
|
||||||
"les/test_flow_control",
|
"les/test_flow_control",
|
||||||
"test_auth",
|
|
||||||
"test_crypt",
|
|
||||||
"test_discovery",
|
|
||||||
"test_ecies",
|
|
||||||
"test_enode",
|
|
||||||
"test_rlpx_thunk",
|
"test_rlpx_thunk",
|
||||||
"test_shh",
|
"test_shh",
|
||||||
"test_shh_config",
|
"test_shh_config",
|
||||||
|
|
|
@ -103,14 +103,14 @@ proc expiration(): uint32 =
|
||||||
|
|
||||||
# Wire protocol
|
# Wire protocol
|
||||||
|
|
||||||
proc send(d: DiscoveryProtocol, n: Node, data: seq[byte]) =
|
proc send(d: DiscoveryProtocol, n: Node, data: seq[byte]) {.raises: [Defect].} =
|
||||||
let ta = initTAddress(n.node.address.ip, n.node.address.udpPort)
|
let ta = initTAddress(n.node.address.ip, n.node.address.udpPort)
|
||||||
let f = d.transp.sendTo(ta, data)
|
let f = d.transp.sendTo(ta, data)
|
||||||
f.callback = proc(data: pointer) {.gcsafe.} =
|
f.callback = proc(data: pointer) {.gcsafe.} =
|
||||||
if f.failed:
|
if f.failed:
|
||||||
debug "Discovery send failed", msg = f.readError.msg
|
debug "Discovery send failed", msg = f.readError.msg
|
||||||
|
|
||||||
proc sendPing*(d: DiscoveryProtocol, n: Node): seq[byte] =
|
proc sendPing*(d: DiscoveryProtocol, n: Node): seq[byte] {.raises: [Defect].} =
|
||||||
let payload = rlp.encode((PROTO_VERSION, d.address, n.node.address,
|
let payload = rlp.encode((PROTO_VERSION, d.address, n.node.address,
|
||||||
expiration()))
|
expiration()))
|
||||||
let msg = pack(cmdPing, payload, d.privKey)
|
let msg = pack(cmdPing, payload, d.privKey)
|
||||||
|
@ -233,8 +233,8 @@ proc expirationValid(cmdId: CommandId, rlpEncodedPayload: openArray[byte]):
|
||||||
else:
|
else:
|
||||||
raise newException(DiscProtocolError, "Invalid RLP list for this packet id")
|
raise newException(DiscProtocolError, "Invalid RLP list for this packet id")
|
||||||
|
|
||||||
proc receive*(d: DiscoveryProtocol, a: Address, msg: openArray[byte]) {.gcsafe.} =
|
proc receive*(d: DiscoveryProtocol, a: Address, msg: openArray[byte])
|
||||||
## Can raise `DiscProtocolError` and all of `RlpError`
|
{.raises: [DiscProtocolError, RlpError, ValueError, Defect].} =
|
||||||
# Note: export only needed for testing
|
# Note: export only needed for testing
|
||||||
let msgHash = validateMsgHash(msg)
|
let msgHash = validateMsgHash(msg)
|
||||||
if msgHash.isOk():
|
if msgHash.isOk():
|
||||||
|
@ -260,23 +260,23 @@ proc receive*(d: DiscoveryProtocol, a: Address, msg: openArray[byte]) {.gcsafe.}
|
||||||
else:
|
else:
|
||||||
notice "Wrong msg mac from ", a
|
notice "Wrong msg mac from ", a
|
||||||
|
|
||||||
proc processClient(transp: DatagramTransport,
|
proc processClient(transp: DatagramTransport, raddr: TransportAddress):
|
||||||
raddr: TransportAddress): Future[void] {.async, gcsafe.} =
|
Future[void] {.async, raises: [Defect].} =
|
||||||
var proto = getUserData[DiscoveryProtocol](transp)
|
var proto = getUserData[DiscoveryProtocol](transp)
|
||||||
|
let buf = try: transp.getMessage()
|
||||||
|
except TransportOsError as e:
|
||||||
|
# This is likely to be local network connection issues.
|
||||||
|
warn "Transport getMessage", exception = e.name, msg = e.msg
|
||||||
|
return
|
||||||
|
let a = Address(ip: raddr.address, udpPort: raddr.port, tcpPort: raddr.port)
|
||||||
try:
|
try:
|
||||||
# TODO: Maybe here better to use `peekMessage()` to avoid allocation,
|
|
||||||
# but `Bytes` object is just a simple seq[byte], and `ByteRange` object
|
|
||||||
# do not support custom length.
|
|
||||||
var buf = transp.getMessage()
|
|
||||||
let a = Address(ip: raddr.address, udpPort: raddr.port, tcpPort: raddr.port)
|
|
||||||
proto.receive(a, buf)
|
proto.receive(a, buf)
|
||||||
except RlpError as e:
|
except RlpError as e:
|
||||||
debug "Receive failed", exc = e.name, err = e.msg
|
debug "Receive failed", exc = e.name, err = e.msg
|
||||||
except DiscProtocolError as e:
|
except DiscProtocolError as e:
|
||||||
debug "Receive failed", exc = e.name, err = e.msg
|
debug "Receive failed", exc = e.name, err = e.msg
|
||||||
except Exception as e:
|
except ValueError as e:
|
||||||
debug "Receive failed", exc = e.name, err = e.msg
|
debug "Receive failed", exc = e.name, err = e.msg
|
||||||
raise e
|
|
||||||
|
|
||||||
proc open*(d: DiscoveryProtocol) =
|
proc open*(d: DiscoveryProtocol) =
|
||||||
# TODO allow binding to specific IP / IPv6 / etc
|
# TODO allow binding to specific IP / IPv6 / etc
|
||||||
|
|
|
@ -26,7 +26,7 @@ type
|
||||||
routing: RoutingTable
|
routing: RoutingTable
|
||||||
pongFutures: Table[seq[byte], Future[bool]]
|
pongFutures: Table[seq[byte], Future[bool]]
|
||||||
pingFutures: Table[Node, Future[bool]]
|
pingFutures: Table[Node, Future[bool]]
|
||||||
neighboursCallbacks: Table[Node, proc(n: seq[Node]) {.gcsafe.}]
|
neighboursCallbacks: Table[Node, proc(n: seq[Node]) {.gcsafe, raises: [Defect].}]
|
||||||
rng: ref BrHmacDrbgContext
|
rng: ref BrHmacDrbgContext
|
||||||
|
|
||||||
NodeId* = UInt256
|
NodeId* = UInt256
|
||||||
|
@ -255,7 +255,7 @@ proc updateRoutingTable(k: KademliaProtocol, n: Node) {.gcsafe.} =
|
||||||
# replacement cache.
|
# replacement cache.
|
||||||
asyncCheck k.bond(evictionCandidate)
|
asyncCheck k.bond(evictionCandidate)
|
||||||
|
|
||||||
proc doSleep(p: proc() {.gcsafe.}) {.async, gcsafe.} =
|
proc doSleep(p: proc() {.gcsafe, raises: [Defect].}) {.async, gcsafe.} =
|
||||||
await sleepAsync(REQUEST_TIMEOUT)
|
await sleepAsync(REQUEST_TIMEOUT)
|
||||||
p()
|
p()
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ proc waitPong(k: KademliaProtocol, n: Node, pingid: seq[byte]): Future[bool] =
|
||||||
k.pongFutures.del(pingid)
|
k.pongFutures.del(pingid)
|
||||||
fut.complete(false)
|
fut.complete(false)
|
||||||
|
|
||||||
proc ping(k: KademliaProtocol, n: Node): seq[byte] =
|
proc ping(k: KademliaProtocol, n: Node): seq[byte] {.raises: [Defect].} =
|
||||||
doAssert(n != k.thisNode)
|
doAssert(n != k.thisNode)
|
||||||
result = k.wire.sendPing(n)
|
result = k.wire.sendPing(n)
|
||||||
|
|
||||||
|
@ -290,12 +290,13 @@ proc waitPing(k: KademliaProtocol, n: Node): Future[bool] {.gcsafe.} =
|
||||||
k.pingFutures.del(n)
|
k.pingFutures.del(n)
|
||||||
fut.complete(false)
|
fut.complete(false)
|
||||||
|
|
||||||
proc waitNeighbours(k: KademliaProtocol, remote: Node): Future[seq[Node]] =
|
proc waitNeighbours(k: KademliaProtocol, remote: Node):
|
||||||
|
Future[seq[Node]] {.raises: [Defect].} =
|
||||||
doAssert(remote notin k.neighboursCallbacks)
|
doAssert(remote notin k.neighboursCallbacks)
|
||||||
result = newFuture[seq[Node]]("waitNeighbours")
|
result = newFuture[seq[Node]]("waitNeighbours")
|
||||||
let fut = result
|
let fut = result
|
||||||
var neighbours = newSeqOfCap[Node](BUCKET_SIZE)
|
var neighbours = newSeqOfCap[Node](BUCKET_SIZE)
|
||||||
k.neighboursCallbacks[remote] = proc(n: seq[Node]) =
|
k.neighboursCallbacks[remote] = proc(n: seq[Node]) {.gcsafe, raises: [Defect].} =
|
||||||
# This callback is expected to be called multiple times because nodes usually
|
# This callback is expected to be called multiple times because nodes usually
|
||||||
# split the neighbours replies into multiple packets, so we only complete the
|
# split the neighbours replies into multiple packets, so we only complete the
|
||||||
# future event.set() we've received enough neighbours.
|
# future event.set() we've received enough neighbours.
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import
|
||||||
|
./test_auth,
|
||||||
|
./test_crypt,
|
||||||
|
./test_discovery,
|
||||||
|
./test_ecies,
|
||||||
|
./test_enode
|
|
@ -10,12 +10,6 @@ proc localAddress*(port: int): Address =
|
||||||
result = Address(udpPort: port, tcpPort: port,
|
result = Address(udpPort: port, tcpPort: port,
|
||||||
ip: parseIpAddress("127.0.0.1"))
|
ip: parseIpAddress("127.0.0.1"))
|
||||||
|
|
||||||
proc startDiscoveryNode*(privKey: PrivateKey, address: Address,
|
|
||||||
bootnodes: seq[ENode]): Future[DiscoveryProtocol] {.async.} =
|
|
||||||
result = newDiscoveryProtocol(privKey, address, bootnodes)
|
|
||||||
result.open()
|
|
||||||
await result.bootstrap()
|
|
||||||
|
|
||||||
proc setupTestNode*(
|
proc setupTestNode*(
|
||||||
rng: ref BrHmacDrbgContext,
|
rng: ref BrHmacDrbgContext,
|
||||||
capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode {.gcsafe.} =
|
capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode {.gcsafe.} =
|
||||||
|
@ -27,13 +21,6 @@ proc setupTestNode*(
|
||||||
for capability in capabilities:
|
for capability in capabilities:
|
||||||
result.addCapability capability
|
result.addCapability capability
|
||||||
|
|
||||||
proc packData*(payload: openArray[byte], pk: PrivateKey): seq[byte] =
|
|
||||||
let
|
|
||||||
payloadSeq = @payload
|
|
||||||
signature = @(pk.sign(payload).toRaw())
|
|
||||||
msgHash = keccak256.digest(signature & payloadSeq)
|
|
||||||
result = @(msgHash.data) & signature & payloadSeq
|
|
||||||
|
|
||||||
template sourceDir*: string = currentSourcePath.rsplit(DirSep, 1)[0]
|
template sourceDir*: string = currentSourcePath.rsplit(DirSep, 1)[0]
|
||||||
|
|
||||||
proc recvMsgMock*(msg: openArray[byte]): tuple[msgId: int, msgData: Rlp] =
|
proc recvMsgMock*(msg: openArray[byte]): tuple[msgId: int, msgData: Rlp] =
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
{.used.}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/unittest,
|
std/unittest,
|
||||||
nimcrypto/[utils, keccak],
|
nimcrypto/[utils, keccak],
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
{.used.}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/unittest,
|
std/unittest,
|
||||||
nimcrypto/[utils, sysrand, keccak],
|
nimcrypto/[utils, sysrand, keccak],
|
||||||
|
|
|
@ -7,119 +7,139 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
{.used.}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[sequtils, unittest],
|
std/sequtils,
|
||||||
chronos, stew/byteutils,
|
chronos, stew/byteutils, nimcrypto, testutils/unittests,
|
||||||
../../eth/[keys, rlp], ../../eth/p2p/[discovery, kademlia, enode],
|
../../eth/keys, ../../eth/p2p/[discovery, kademlia, enode]
|
||||||
./p2p_test_helper
|
|
||||||
|
proc localAddress(port: int): Address =
|
||||||
|
let port = Port(port)
|
||||||
|
result = Address(udpPort: port, tcpPort: port,
|
||||||
|
ip: parseIpAddress("127.0.0.1"))
|
||||||
|
|
||||||
|
proc initDiscoveryNode(privKey: PrivateKey, address: Address,
|
||||||
|
bootnodes: seq[ENode]): DiscoveryProtocol =
|
||||||
|
let node = newDiscoveryProtocol(privKey, address, bootnodes)
|
||||||
|
node.open()
|
||||||
|
|
||||||
|
return node
|
||||||
|
|
||||||
|
proc packData(payload: openArray[byte], pk: PrivateKey): seq[byte] =
|
||||||
|
let
|
||||||
|
payloadSeq = @payload
|
||||||
|
signature = @(pk.sign(payload).toRaw())
|
||||||
|
msgHash = keccak256.digest(signature & payloadSeq)
|
||||||
|
result = @(msgHash.data) & signature & payloadSeq
|
||||||
|
|
||||||
proc nodeIdInNodes(id: NodeId, nodes: openarray[Node]): bool =
|
proc nodeIdInNodes(id: NodeId, nodes: openarray[Node]): bool =
|
||||||
for n in nodes:
|
for n in nodes:
|
||||||
if id == n.id: return true
|
if id == n.id: return true
|
||||||
|
|
||||||
proc test() {.async.} =
|
procSuite "Discovery Tests":
|
||||||
suite "Discovery Tests":
|
let
|
||||||
|
bootNodeKey = PrivateKey.fromHex(
|
||||||
|
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[]
|
||||||
|
bootNodeAddr = localAddress(20301)
|
||||||
|
bootENode = ENode(pubkey: bootNodeKey.toPublicKey(), address: bootNodeAddr)
|
||||||
|
bootNode = initDiscoveryNode(bootNodeKey, bootNodeAddr, @[])
|
||||||
|
waitFor bootNode.bootstrap()
|
||||||
|
|
||||||
|
asyncTest "Discover nodes":
|
||||||
|
let nodeKeys = [
|
||||||
|
PrivateKey.fromHex(
|
||||||
|
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[],
|
||||||
|
PrivateKey.fromHex(
|
||||||
|
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619")[],
|
||||||
|
PrivateKey.fromHex(
|
||||||
|
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a620")[]
|
||||||
|
]
|
||||||
|
|
||||||
|
var nodes: seq[DiscoveryProtocol]
|
||||||
|
for i in 0..<nodeKeys.len:
|
||||||
|
let node = initDiscoveryNode(nodeKeys[i], localAddress(20302 + i),
|
||||||
|
@[bootENode])
|
||||||
|
nodes.add(node)
|
||||||
|
|
||||||
|
await allFutures(nodes.mapIt(it.bootstrap()))
|
||||||
|
nodes.add(bootNode)
|
||||||
|
|
||||||
|
for i in nodes:
|
||||||
|
for j in nodes:
|
||||||
|
if j != i:
|
||||||
|
check(nodeIdInNodes(i.thisNode.id, j.randomNodes(nodes.len - 1)))
|
||||||
|
|
||||||
|
test "Test Vectors":
|
||||||
|
# These are the test vectors from EIP-8:
|
||||||
|
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md#rlpx-discovery-protocol
|
||||||
|
# However they are unpacked and the expiration is changed from 0x43b9a355
|
||||||
|
# to 0x6fd3aed7 so that they remain valid for a while
|
||||||
|
let validProtocolData = [
|
||||||
|
# ping packet with version 4, additional list elements
|
||||||
|
"01ec04cb847f000001820cfa8215a8d790000000000000000000000000000000018208ae820d05846fd3aed70102",
|
||||||
|
# ping packet with version 555, additional list elements and additional random data
|
||||||
|
"01f83e82022bd79020010db83c4d001500000000abcdef12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a846fd3aed7c5010203040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba76023fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee1917084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c76d922dc3",
|
||||||
|
# pong packet with additional list elements and additional random data
|
||||||
|
"02f846d79020010db885a308d313198a2e037073488208ae82823aa0fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c954846fd3aed7c6010203c2040506a0c969a58f6f9095004c0177a6b47f451530cab38966a25cca5cb58f055542124e",
|
||||||
|
# findnode packet with additional list elements and additional random data
|
||||||
|
"03f84eb840ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f846fd3aed782999983999999280dc62cc8255c73471e0a61da0c89acdc0e035e260add7fc0c04ad9ebf3919644c91cb247affc82b69bd2ca235c71eab8e49737c937a2c396",
|
||||||
|
# neighbours packet with additional list elements and additional random data
|
||||||
|
"04f9015bf90150f84d846321163782115c82115db8403155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32f84984010203040101b840312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069dbf8599020010db83c4d001500000000abcdef12820d05820d05b84038643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aacf8599020010db885a308d313198a2e037073488203e78203e8b8408dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df73846fd3aed7010203b525a138aa34383fec3d2719a0",
|
||||||
|
]
|
||||||
let
|
let
|
||||||
bootNodeKey = PrivateKey.fromHex(
|
address = localAddress(20302)
|
||||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[]
|
nodeKey = PrivateKey.fromHex(
|
||||||
bootNodeAddr = localAddress(20301)
|
"b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")[]
|
||||||
bootENode = ENode(pubkey: bootNodeKey.toPublicKey(), address: bootNodeAddr)
|
|
||||||
bootNode = await startDiscoveryNode(bootNodeKey, bootNodeAddr, @[])
|
|
||||||
|
|
||||||
test "Discover nodes":
|
for data in validProtocolData:
|
||||||
let nodeKeys = [
|
# none of these may raise
|
||||||
PrivateKey.fromHex(
|
bootNode.receive(address, packData(hexToSeqByte(data), nodeKey))
|
||||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[],
|
|
||||||
PrivateKey.fromHex(
|
|
||||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619")[],
|
|
||||||
PrivateKey.fromHex(
|
|
||||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a620")[]
|
|
||||||
]
|
|
||||||
var nodeAddrs = newSeqOfCap[Address](nodeKeys.len)
|
|
||||||
for i in 0 ..< nodeKeys.len: nodeAddrs.add(localAddress(20302 + i))
|
|
||||||
|
|
||||||
var nodes = await all(zip(nodeKeys, nodeAddrs).mapIt(
|
test "Invalid protocol data":
|
||||||
startDiscoveryNode(it[0], it[1], @[bootENode]))
|
let invalidProtocolData = [
|
||||||
)
|
"0x00", # invalid msg id
|
||||||
nodes.add(bootNode)
|
"0x01", # empty payload
|
||||||
|
"0x03b8", # no list but string
|
||||||
|
"0x01C0", # empty list
|
||||||
|
# FindNode target that is 1 byte too long
|
||||||
|
# We currently do not raise on this, so can't really test it
|
||||||
|
# "0x03f847b841AA0000000000000000000000000000000000000000000000000000000000000000a99a96bd988e1839272f93257bd9dfb2e558390e1f9bff28cdc8f04c9b5d06b1846fd3aed7",
|
||||||
|
]
|
||||||
|
let
|
||||||
|
address = localAddress(20302)
|
||||||
|
nodeKey = PrivateKey.fromHex(
|
||||||
|
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[]
|
||||||
|
|
||||||
for i in nodes:
|
for data in invalidProtocolData:
|
||||||
for j in nodes:
|
expect DiscProtocolError:
|
||||||
if j != i:
|
|
||||||
check(nodeIdInNodes(i.thisNode.id, j.randomNodes(nodes.len - 1)))
|
|
||||||
|
|
||||||
test "Test Vectors":
|
|
||||||
# These are the test vectors from EIP-8:
|
|
||||||
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md#rlpx-discovery-protocol
|
|
||||||
# However they are unpacked and the expiration is changed from 0x43b9a355
|
|
||||||
# to 0x6fd3aed7 so that they remain valid for a while
|
|
||||||
let validProtocolData = [
|
|
||||||
# ping packet with version 4, additional list elements
|
|
||||||
"01ec04cb847f000001820cfa8215a8d790000000000000000000000000000000018208ae820d05846fd3aed70102",
|
|
||||||
# ping packet with version 555, additional list elements and additional random data
|
|
||||||
"01f83e82022bd79020010db83c4d001500000000abcdef12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a846fd3aed7c5010203040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba76023fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee1917084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c76d922dc3",
|
|
||||||
# pong packet with additional list elements and additional random data
|
|
||||||
"02f846d79020010db885a308d313198a2e037073488208ae82823aa0fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c954846fd3aed7c6010203c2040506a0c969a58f6f9095004c0177a6b47f451530cab38966a25cca5cb58f055542124e",
|
|
||||||
# findnode packet with additional list elements and additional random data
|
|
||||||
"03f84eb840ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f846fd3aed782999983999999280dc62cc8255c73471e0a61da0c89acdc0e035e260add7fc0c04ad9ebf3919644c91cb247affc82b69bd2ca235c71eab8e49737c937a2c396",
|
|
||||||
# neighbours packet with additional list elements and additional random data
|
|
||||||
"04f9015bf90150f84d846321163782115c82115db8403155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32f84984010203040101b840312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069dbf8599020010db83c4d001500000000abcdef12820d05820d05b84038643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aacf8599020010db885a308d313198a2e037073488203e78203e8b8408dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df73846fd3aed7010203b525a138aa34383fec3d2719a0",
|
|
||||||
]
|
|
||||||
let
|
|
||||||
address = localAddress(20302)
|
|
||||||
nodeKey = PrivateKey.fromHex(
|
|
||||||
"b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")[]
|
|
||||||
|
|
||||||
for data in validProtocolData:
|
|
||||||
# none of these may raise
|
|
||||||
bootNode.receive(address, packData(hexToSeqByte(data), nodeKey))
|
bootNode.receive(address, packData(hexToSeqByte(data), nodeKey))
|
||||||
|
|
||||||
test "Invalid protocol data":
|
# empty msg id and payload, doesn't raise, just fails and prints wrong
|
||||||
let invalidProtocolData = [
|
# msg mac
|
||||||
"0x00", # invalid msg id
|
bootNode.receive(address, packData(@[], nodeKey))
|
||||||
"0x01", # empty payload
|
|
||||||
"0x03b8", # no list but string
|
|
||||||
"0x01C0", # empty list
|
|
||||||
# FindNode target that is 1 byte too long
|
|
||||||
# We currently do not raise on this, so can't really test it
|
|
||||||
# "0x03f847b841AA0000000000000000000000000000000000000000000000000000000000000000a99a96bd988e1839272f93257bd9dfb2e558390e1f9bff28cdc8f04c9b5d06b1846fd3aed7",
|
|
||||||
]
|
|
||||||
let
|
|
||||||
address = localAddress(20302)
|
|
||||||
nodeKey = PrivateKey.fromHex(
|
|
||||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[]
|
|
||||||
|
|
||||||
for data in invalidProtocolData:
|
asyncTest "Two findNode calls for the same peer in rapid succession":
|
||||||
expect DiscProtocolError:
|
let targetKey = PrivateKey.fromHex(
|
||||||
bootNode.receive(address, packData(hexToSeqByte(data), nodeKey))
|
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[]
|
||||||
|
let peerKey = PrivateKey.fromHex(
|
||||||
|
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619")[]
|
||||||
|
|
||||||
# empty msg id and payload, doesn't raise, just fails and prints wrong
|
let targetNodeId = kademlia.toNodeId(targetKey.toPublicKey)
|
||||||
# msg mac
|
let peerNode = kademlia.newNode(peerKey.toPublicKey, localAddress(20302))
|
||||||
bootNode.receive(address, packData(@[], nodeKey))
|
let nodesSeen = new(HashSet[Node])
|
||||||
|
|
||||||
test "Two findNode calls for the same peer in rapid succession":
|
# Start `findNode` but don't `await` yet, so the reply can't be processed yet.
|
||||||
let targetKey = PrivateKey.fromHex(
|
let neighbours1Future = bootNode.kademlia.findNode(nodesSeen, targetNodeId, peerNode)
|
||||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[]
|
|
||||||
let peerKey = PrivateKey.fromHex(
|
|
||||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619")[]
|
|
||||||
|
|
||||||
let targetNodeId = kademlia.toNodeId(targetKey.toPublicKey)
|
# This will raise an assertion error if `findNode` doesn't check for and ignore
|
||||||
let peerNode = kademlia.newNode(peerKey.toPublicKey, localAddress(20302))
|
# this second call to the same target and peer in rapid successfion.
|
||||||
let nodesSeen = new(HashSet[Node])
|
let neighbours2Future = bootNode.kademlia.findNode(nodesSeen, targetNodeId, peerNode)
|
||||||
|
|
||||||
# Start `findNode` but don't `await` yet, so the reply can't be processed yet.
|
# Just for completness, verify the result is empty from the second call.
|
||||||
let neighbours1Future = bootNode.kademlia.findNode(nodesSeen, targetNodeId, peerNode)
|
let neighbours2 = await neighbours2Future
|
||||||
|
check(neighbours2.len == 0)
|
||||||
|
|
||||||
# This will raise an assertion error if `findNode` doesn't check for and ignore
|
# Just for completeness, wait for the first result out of order.
|
||||||
# this second call to the same target and peer in rapid successfion.
|
# Max delay 5 seconds.
|
||||||
let neighbours2Future = bootNode.kademlia.findNode(nodesSeen, targetNodeId, peerNode)
|
discard await neighbours1Future
|
||||||
|
|
||||||
# Just for completness, verify the result is empty from the second call.
|
|
||||||
let neighbours2 = await neighbours2Future
|
|
||||||
check(neighbours2.len == 0)
|
|
||||||
|
|
||||||
# Just for completeness, wait for the first result out of order.
|
|
||||||
# Max delay 5 seconds.
|
|
||||||
discard await neighbours1Future
|
|
||||||
|
|
||||||
waitFor test()
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
{.used.}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/unittest,
|
std/unittest,
|
||||||
nimcrypto/[utils, sha2, hmac, rijndael],
|
nimcrypto/[utils, sha2, hmac, rijndael],
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
# Apache License, version 2.0, (LICENSE-APACHEv2)
|
# Apache License, version 2.0, (LICENSE-APACHEv2)
|
||||||
# MIT license (LICENSE-MIT)
|
# MIT license (LICENSE-MIT)
|
||||||
|
|
||||||
|
{.used.}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[unittest, net, options],
|
std/[unittest, net, options],
|
||||||
../../eth/p2p/enode
|
../../eth/p2p/enode
|
||||||
|
|
Loading…
Reference in New Issue